diff --git a/README.md b/README.md
index 627657f..e210fe5 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# SparkFun_Template_Arduino_Library
+# SparkFun_Qwiic_Ultrasonic_Arduino_Library
========================================
diff --git a/documents/HC_SR04_Datasheet.pdf b/documents/HC_SR04_Datasheet.pdf
new file mode 100644
index 0000000..fcd6f54
Binary files /dev/null and b/documents/HC_SR04_Datasheet.pdf differ
diff --git a/documents/add_documents_here.md b/documents/add_documents_here.md
deleted file mode 100644
index 2010408..0000000
--- a/documents/add_documents_here.md
+++ /dev/null
@@ -1 +0,0 @@
-Add any relevant documents to this director (eg. datasheet), and delete this file.
diff --git a/examples/Example01_BasicUsage/Example01_BasicUsage.ino b/examples/Example01_BasicUsage/Example01_BasicUsage.ino
deleted file mode 100644
index b308416..0000000
--- a/examples/Example01_BasicUsage/Example01_BasicUsage.ino
+++ /dev/null
@@ -1,22 +0,0 @@
-// TODO: Add includes as needed
-#include "SparkFun_Template_Arduino_Library.h"
-
-// TODO: Change Template
-TempalteClass myDevice;
-
-void setup()
-{
- // Start serial
- Serial.begin(115200);
- Serial.println("Template Example 1 - Basic Uasge"); // TODO: Update
-
- // TODO: Check return value of begin
- myDevice.begin();
-
- // TODO: Add other setup code if needed. Most setup should be done in begin()
-}
-
-void loop()
-{
- // TODO: Demonstrate minimal code needed for basic usage
-}
\ No newline at end of file
diff --git a/examples/Example1_BasicReadings/Example1_BasicReadings.ino b/examples/Example1_BasicReadings/Example1_BasicReadings.ino
new file mode 100644
index 0000000..73cfe8b
--- /dev/null
+++ b/examples/Example1_BasicReadings/Example1_BasicReadings.ino
@@ -0,0 +1,44 @@
+#include "SparkFun_Qwiic_Ultrasonic_Arduino_Library.h"
+
+// Create an ultrasonic sensor object
+QwiicUltrasonic myUltrasonic;
+
+// Here we set the device address. Note that an older version of the Qwiic
+// Ultrasonic firmware used a default address of 0x00. If yours uses 0x00,
+// you'll need to change the address below. It is also recommended to run
+// Example 2 to change the address to the new default.
+uint8_t deviceAddress = kQwiicUltrasonicDefaultAddress; // 0x2F
+// uint8_t deviceAddress = 0x00;
+
+void setup()
+{
+ // Start serial
+ Serial.begin(115200);
+ Serial.println("Qwiic Ultrasonic Example 1 - Basic Readings");
+
+ Wire.begin();
+
+ // Attempt to begin the sensor
+ while (myUltrasonic.begin(deviceAddress) == false)
+ {
+ Serial.println("Ultrasonic sensor not connected, check your wiring and I2C address!");
+ delay(1000);
+ }
+
+ Serial.println("Ultrasonic sensor connected!");
+}
+
+void loop()
+{
+ // Get measurement from sensor. Note that the mesaured distance actually
+ // comes from the previous trigger, so measurements will be slightly delayed
+ uint16_t distance = 0;
+ myUltrasonic.triggerAndRead(distance);
+
+ // Print measurement
+ Serial.print("Distance (mm): ");
+ Serial.println(distance);
+
+ // Wait a bit
+ delay(100);
+}
\ No newline at end of file
diff --git a/examples/Example2_ChangeAddress/Example2_ChangeAddress.ino b/examples/Example2_ChangeAddress/Example2_ChangeAddress.ino
new file mode 100644
index 0000000..c94577c
--- /dev/null
+++ b/examples/Example2_ChangeAddress/Example2_ChangeAddress.ino
@@ -0,0 +1,94 @@
+#include "SparkFun_Qwiic_Ultrasonic_Arduino_Library.h"
+
+// Create an ultrasonic sensor object
+QwiicUltrasonic myUltrasonic;
+
+// Here we set the device address. Note that an older version of the Qwiic
+// Ultrasonic firmware used a default address of 0x00. If yours uses 0x00,
+// you'll need to change the address below. It is also recommended to run
+// Example 2 to change the address to the new default.
+uint8_t deviceAddress = kQwiicUltrasonicDefaultAddress; // 0x2F
+// uint8_t deviceAddress = 0x00;
+
+void setup()
+{
+ // Start serial
+ Serial.begin(115200);
+ Serial.println("Qwiic Ultrasonic Example 2 - Change Address");
+
+ Wire.begin();
+
+ // Attempt to begin the sensor
+ while (myUltrasonic.begin(deviceAddress) == false)
+ {
+ Serial.println("Ultrasonic sensor not connected, check your wiring and I2C address!");
+ delay(1000);
+ }
+
+ Serial.println("Ultrasonic sensor connected!");
+
+ // Repeat until the address has been successfully changed
+ bool addressChanged = false;
+ while (addressChanged == false)
+ {
+ // Print instructions
+ Serial.println();
+ Serial.println("Please enter a new address for the sensor.");
+ Serial.println("Any value between 0x20 and 0x2F is valid.");
+ Serial.println("Enter the address in hexadecimal without the `0x`.");
+ Serial.println();
+
+ // Clear serial buffer and wait for input
+ while (Serial.available() > 0)
+ Serial.read();
+ while (Serial.available() == 0)
+ ;
+
+ // Read input from user
+ char input[4]; // Only expecting a few characters
+ size_t numBytesRead = Serial.readBytesUntil('\n', input, 4);
+
+ // Parse input using strtoul (STRing TO Unsigned Long integer)
+ uint8_t newAddress = strtoul(input, nullptr, 16);
+
+ Serial.print("Parsed address: ");
+ Serial.println(newAddress, HEX);
+
+ // Check if the address is valid
+ if (newAddress < kQwiicUltrasonicMinAddress || newAddress > kQwiicUltrasonicMaxAddress)
+ {
+ Serial.println("Invalid address!");
+ continue;
+ }
+
+ // Address is valid, attempt to change it on the device
+ sfeTkError_t err = myUltrasonic.changeAddress(newAddress);
+
+ // Check whether the address was changed successfully
+ if (err)
+ Serial.println("Failed to change address!");
+
+ // Success, we're done here!
+ addressChanged = true;
+ }
+
+ Serial.println("Address changed successfully! Continuing...");
+
+ // Wait a moment so user can read the messages
+ delay(1000);
+}
+
+void loop()
+{
+ // Get measurement from sensor. Note that the mesaured distance actually
+ // comes from the previous trigger, so measurements will be slightly delayed
+ uint16_t distance = 0;
+ myUltrasonic.triggerAndRead(distance);
+
+ // Print measurement
+ Serial.print("Distance (mm): ");
+ Serial.println(distance);
+
+ // Wait a bit
+ delay(100);
+}
\ No newline at end of file
diff --git a/keywords.txt b/keywords.txt
index 2344c7f..a4091f6 100644
--- a/keywords.txt
+++ b/keywords.txt
@@ -1,29 +1,27 @@
#########################################################
-# Syntax Coloring Map for TODO: Add name #
+# Syntax Coloring Map for the Qwiic Ultrasonic Sensor #
#########################################################
# Class
#########################################################
-# TODO: Add this
-TemplateClass KEYWORD1
+QwiicUltrasonic KEYWORD1
#########################################################
# Methods and Functions
#########################################################
-# TODO: Add these
begin KEYWORD2
+isConnected KEYWORD2
+triggerAndRead KEYWORD2
+changeAddress KEYWORD2
#########################################################
# Constants
#########################################################
-# TODO: Add these
-TEMPALTE_CONSTANT LITERAL1
-
-#########################################################
-# Structs
-#########################################################
-
-# TODO: Add these
-template_struct_t LITERAL3
\ No newline at end of file
+QWIIC_ULTRASONIC_ADDRESSES LITERAL1
+QWIIC_ULTRASONIC_NUM_ADDRESSES LITERAL1
+QWIIC_ULTRASONIC_MIN_ADDRESS LITERAL1
+QWIIC_ULTRASONIC_MAX_ADDRESS LITERAL1
+QWIIC_ULTRASONIC_DEFAULT_ADDRESS LITERAL1
+QWIIC_ULTRASONIC_REGISTER_TRIGGER LITERAL1
diff --git a/library.properties b/library.properties
index a1a6c01..bf9d5be 100644
--- a/library.properties
+++ b/library.properties
@@ -1,9 +1,9 @@
-name=SparkFun Template Arduino Library
+name=SparkFun Qwiic Ultrasonic Arduino Library
version=1.0.0
author=SparkFun Electronics
maintainer=SparkFun Electronics
-sentence=TODO: Add short description
-paragraph=TODO: Add long description
-category=TODO: Add category (Sensors, Display, Communication, etc.)
-url=TODO: Add URL
-architectures=TODO: Add architectures (*, esp32, teensy, stm32, megaavr, etc.)
\ No newline at end of file
+sentence=A library to use the SparkFun Qwiic Ultrasonic Distance Sensor
+paragraph=
+category=Sensors
+url=https://github.com/sparkfun/SparkFun_Qwiic_Ultrasonic_Arduino_Library
+architectures=*
\ No newline at end of file
diff --git a/src/SparkFun_Qwiic_Ultrasonic_Arduino_Library.h b/src/SparkFun_Qwiic_Ultrasonic_Arduino_Library.h
new file mode 100644
index 0000000..494fd9d
--- /dev/null
+++ b/src/SparkFun_Qwiic_Ultrasonic_Arduino_Library.h
@@ -0,0 +1,32 @@
+#pragma once
+
+#include "Arduino.h"
+#include "sfeQwiicUltrasonic.h"
+#include
+
+class QwiicUltrasonic : public sfeQwiicUltrasonic
+{
+ public:
+ /// @brief Begins the Qwiic Ultrasonic sensor
+ /// @param address I2C device address to use for the sensor
+ /// @param wirePort Wire port to use for I2C communication
+ /// @return True if successful, false otherwise
+ bool begin(uint8_t address = kQwiicUltrasonicDefaultAddress, TwoWire &wirePort = Wire)
+ {
+ // Setup Arudino I2C bus
+ _theI2CBus.init(wirePort, address);
+
+ // Begin the sensor
+ return sfeQwiicUltrasonic::begin(&_theI2CBus) == kSTkErrOk;
+ }
+
+ /// @brief Checks if the Qwiic Ultrasonic sensor is connected
+ /// @return True if the sensor is connected, false otherwise
+ bool isConnected()
+ {
+ return sfeQwiicUltrasonic::isConnected() == kSTkErrOk;
+ }
+
+ private:
+ sfeTkArdI2C _theI2CBus;
+};
diff --git a/src/SparkFun_Template_Arduino_Library.cpp b/src/SparkFun_Template_Arduino_Library.cpp
deleted file mode 100644
index f27ea73..0000000
--- a/src/SparkFun_Template_Arduino_Library.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "SparkFun_Template_Arduino_Library.h"
-
-BMI270::BMI270()
-{
- // TODO: Initialize variables
-}
-
-int8_t BMI270::begin()
-{
- // TODO: Check if device is connected
-
- // TODO: Initialize hardware
-
- // TODO: Return whether successful
- return false;
-}
diff --git a/src/SparkFun_Template_Arduino_Library.h b/src/SparkFun_Template_Arduino_Library.h
deleted file mode 100644
index f7756e2..0000000
--- a/src/SparkFun_Template_Arduino_Library.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-// TODO: Add includes as needed (e.g. #include , #include )
-#include "Arduino.h"
-
-// TODO: Add constants
-
-// TODO: Implement class
-class TemplateClass
-{
- public:
- /// @brief TODO
- TemplateClass();
-
- /// @brief TODO
- /// @return TODO
- bool begin();
-
- // TODO: Add other methods as needed
-};
diff --git a/src/sfeQwiicUltrasonic.cpp b/src/sfeQwiicUltrasonic.cpp
new file mode 100644
index 0000000..d9b450b
--- /dev/null
+++ b/src/sfeQwiicUltrasonic.cpp
@@ -0,0 +1,74 @@
+#include "sfeQwiicUltrasonic.h"
+
+sfeTkError_t sfeQwiicUltrasonic::begin(sfeTkII2C *theBus)
+{
+ // Nullptr check
+ if (theBus == nullptr)
+ return kSTkErrFail;
+
+ // Check the device address
+ if (theBus->address() < kQwiicUltrasonicMinAddress || theBus->address() > kQwiicUltrasonicMaxAddress)
+ {
+ // An older version of the firmware used 0x00 as the default address.
+ // It's not really a valid address, but we need to allow it. Any other
+ // address can't be used
+ if (theBus->address() != 0x00)
+ return kSTkErrFail;
+ }
+
+ // Set bus pointer
+ _theBus = theBus;
+
+ // Just check if the device is connected, no other setup is needed
+ return isConnected();
+}
+
+sfeTkError_t sfeQwiicUltrasonic::isConnected()
+{
+ // Just ping the device address, there's no product ID register to check
+ return _theBus->ping();
+}
+
+sfeTkError_t sfeQwiicUltrasonic::triggerAndRead(uint16_t &distance)
+{
+ size_t bytesRead = 0;
+ uint8_t rawData[2] = {0, 0};
+
+ // Attempt to read the distance
+ sfeTkError_t err = _theBus->readRegisterRegion(kQwiicUltrasonicRegisterTrigger, rawData, 2, bytesRead);
+
+ // Check whether the read was successful
+ if (err != kSTkErrOk)
+ return err;
+
+ // Store raw data
+ distance = (rawData[0] << 8) | rawData[1];
+
+ // Done!
+ return kSTkErrOk;
+}
+
+sfeTkError_t sfeQwiicUltrasonic::changeAddress(const uint8_t &address)
+{
+ // Check whether the address is valid
+ if (address < kQwiicUltrasonicMinAddress || address > kQwiicUltrasonicMaxAddress)
+ return kSTkErrFail;
+
+ // Write the new address to the device. The first bit must be set to 1
+ sfeTkError_t err = _theBus->writeByte(address | 0x80);
+
+ // Check whether the write was successful
+ if (err != kSTkErrOk)
+ return err;
+
+ // Update the address in the bus
+ _theBus->setAddress(address);
+
+ // Done!
+ return kSTkErrOk;
+}
+
+uint8_t sfeQwiicUltrasonic::getAddress()
+{
+ return _theBus->address();
+}
diff --git a/src/sfeQwiicUltrasonic.h b/src/sfeQwiicUltrasonic.h
new file mode 100644
index 0000000..376a354
--- /dev/null
+++ b/src/sfeQwiicUltrasonic.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "SparkFun_Toolkit.h"
+#include
+
+// Available I2C addresses of the Qwiic Ultrasonic
+const uint8_t kQwiicUltrasonicAddresses[] = {0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F};
+const uint8_t kQwiicUltrasonicNumAddresses = sizeof(kQwiicUltrasonicAddresses) / sizeof(uint8_t);
+const uint8_t kQwiicUltrasonicMinAddress = kQwiicUltrasonicAddresses[0];
+const uint8_t kQwiicUltrasonicMaxAddress = kQwiicUltrasonicAddresses[15];
+const uint8_t kQwiicUltrasonicDefaultAddress = 0x2F;
+
+// Register to trigger a new measuremnt and read the previous one
+const uint8_t kQwiicUltrasonicRegisterTrigger = 0x01;
+
+class sfeQwiicUltrasonic
+{
+ public:
+ /// @brief Default constructor
+ sfeQwiicUltrasonic() : _theBus(nullptr)
+ {
+ }
+
+ /// @brief Begins the Qwiic Ultrasonic sensor
+ /// @param theBus I2C bus to use for communication
+ /// @return 0 for succuss, negative for errors, positive for warnings
+ sfeTkError_t begin(sfeTkII2C *theBus = nullptr);
+
+ /// @brief Checks if the Qwiic Ultrasonic sensor is connected
+ /// @return 0 for succuss, negative for errors, positive for warnings
+ sfeTkError_t isConnected();
+
+ /// @brief Triggers a new measurement and reads the previous one
+ /// @param distance Distance in mm
+ /// @return 0 for succuss, negative for errors, positive for warnings
+ sfeTkError_t triggerAndRead(uint16_t &distance);
+
+ /// @brief Changes the I2C address of the Qwiic Ultrasonic sensor
+ /// @param address New address, must be in the range 0x20 to 0x2F
+ /// @return 0 for succuss, negative for errors, positive for warnings
+ sfeTkError_t changeAddress(const uint8_t &address);
+
+ /// @brief Gets the current I2C address of the Qwiic Ultrasonic sensor
+ /// @return The current I2C address, 7-bit unshifted
+ uint8_t getAddress();
+
+ protected:
+ sfeTkII2C *_theBus;
+};