From 4a32d32080ec8015e2d88b83b77f6ccd7c055c8c Mon Sep 17 00:00:00 2001 From: Richard Patching Date: Wed, 16 Apr 2025 21:00:32 +0100 Subject: [PATCH] Add build instructions --- .cargo/config.toml | 16 +++ .github/ISSUE_TEMPLATE/bug_report.md | 34 +++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++ .github/ISSUE_TEMPLATE/hardware_issue.md | 35 +++++++ .github/pull_request_template.md | 27 ++++++ .github/workflows/rust_ci.yml | 42 ++++++++ .gitignore | 31 ++++++ CODE_OF_CONDUCT.md | 53 ++++++++++ Cargo.toml | 31 ++++++ LICENSE | 21 ++++ README.md | 48 +++++++++ build.rs | 3 + config/display_config.toml | 35 +++++++ config/gps_config.toml | 19 ++++ docs/NEO-6M_SETUP.md | 113 ++++++++++++++++++++++ docs/TFT_SETUP.md | 73 ++++++++++++++ rust-toolchain.toml | 2 + sdkconfig.defaults | 10 ++ src/main.rs | 92 ++++++++++++++++++ 19 files changed, 705 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/hardware_issue.md create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/rust_ci.yml create mode 100644 .gitignore create mode 100644 CODE_OF_CONDUCT.md create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 build.rs create mode 100644 config/display_config.toml create mode 100644 config/gps_config.toml create mode 100644 docs/NEO-6M_SETUP.md create mode 100644 docs/TFT_SETUP.md create mode 100644 rust-toolchain.toml create mode 100644 sdkconfig.defaults create mode 100644 src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..f632639 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,16 @@ +[build] +target = "xtensa-esp32-espidf" + +[target.xtensa-esp32-espidf] +linker = "ldproxy" +runner = "espflash flash --monitor" +rustflags = [ "--cfg", "espidf_time64"] + +[unstable] +build-std = ["std", "panic_abort"] + +[env] +MCU="esp32" +# Note: this variable is not used by the pio builder (`cargo build --features pio`) +ESP_IDF_VERSION = "v5.2.3" + diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..641a102 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,34 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Flash firmware to '...' +2. Connect '....' +3. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Hardware Setup** +- ESP32 Board: [e.g., ESP32-DevKitC] +- GPS Module: [e.g., NEO-6M] +- Display: [e.g., 1.8" TFT] +- Connected peripherals: + +**Software Environment** +- Rust version: [e.g., 1.77] +- ESP-IDF version: +- Operating System: + +**Additional context** +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..5620a44 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/hardware_issue.md b/.github/ISSUE_TEMPLATE/hardware_issue.md new file mode 100644 index 0000000..61c2354 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/hardware_issue.md @@ -0,0 +1,35 @@ +--- +name: Hardware issue +about: Report a hardware-related problem or compatibility issue +title: '[HARDWARE] ' +labels: hardware +assignees: '' + +--- + +**Hardware Configuration** +- ESP32 Board Model: +- GPS Module: +- Display Type: +- Power Supply: +- Other Connected Components: + +**Issue Description** +A clear description of the hardware issue. + +**Expected Behavior** +What you expected to happen. + +**Actual Behavior** +What actually happened. + +**Photos/Diagrams** +If applicable, add photos or diagrams to help explain your problem. + +**Environment** +- Temperature: +- Indoor/Outdoor: +- Weather Conditions (if relevant): + +**Additional Context** +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..d234e7c --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,27 @@ +## Description +Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. + +Fixes # (issue) + +## Type of change +Please delete options that are not relevant. + +- [ ] Bug fix (non-breaking change which fixes an issue) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] This change requires a documentation update + +## How Has This Been Tested? +Please describe the tests that you ran to verify your changes. + +- [ ] Test A +- [ ] Test B + +## Checklist: +- [ ] My code follows the style guidelines of this project +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes \ No newline at end of file diff --git a/.github/workflows/rust_ci.yml b/.github/workflows/rust_ci.yml new file mode 100644 index 0000000..58561f8 --- /dev/null +++ b/.github/workflows/rust_ci.yml @@ -0,0 +1,42 @@ +name: Continuous Integration + +on: + push: + branches: + - main + paths-ignore: + - "**/README.md" + pull_request: + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + rust-checks: + name: Rust Checks + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + action: + - command: build + args: --release + - command: fmt + args: --all -- --check --color always + - command: clippy + args: --all-targets --all-features --workspace -- -D warnings + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Setup Rust + uses: esp-rs/xtensa-toolchain@v1.5 + with: + default: true + buildtargets: esp32 + ldproxy: true + - name: Enable caching + uses: Swatinem/rust-cache@v2 + - name: Run command + run: cargo ${{ matrix.action.command }} ${{ matrix.action.args }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7d27fcd --- /dev/null +++ b/.gitignore @@ -0,0 +1,31 @@ +# Rust +/target +**/*.rs.bk +Cargo.lock + +# IDE +/.vscode +/.idea +*.swp +*.swo + +# Build +/.embuild +/dist + +# Environment +.env +.env.local +.env.*.local + +# System +.DS_Store +Thumbs.db + +# Debug +*.log +*.debug + +# Backup +*.bak +*~ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..cfbbb19 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,53 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes +* Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +[INSERT CONTACT METHOD]. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8a1f07e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "aniker" +version = "0.1.0" +authors = ["Richard Patching "] +edition = "2021" +resolver = "2" +rust-version = "1.77" + +[[bin]] +name = "aniker" +harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors + +[profile.release] +opt-level = "s" + +[profile.dev] +debug = true # Symbols are nice and they don't increase the size on Flash +opt-level = "z" + +[features] +default = [] + +experimental = ["esp-idf-svc/experimental"] + +[dependencies] +log = "0.4" +esp-idf-svc = { version = "0.51", features = ["critical-section", "embassy-time-driver", "embassy-sync"] } +aniker-gps = { path = "../aniker-gps" } + +[build-dependencies] +embuild = "0.33" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0273d99 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Richard Patching + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..24068fa --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# Aniker - ESP32 GPS Anchor Alarm + +## Hardware Requirements + +### Required Components +- ESP32 development board +- NEO-6M GPS module +- 1.8" TFT SPI Display (128x160 resolution) +- Connecting wires +- Power supply (USB or battery - specifications TBD) + +### Display Specifications +- Resolution: 128x160 pixels +- Interface: SPI +- Size: 1.8 inch +- Controller: ST7735 (common for this display type) +- Color Depth: 16-bit (65K colors) + +### GPS Module Specifications (NEO-6M) +- Operating voltage: 3.3V +- Communication: UART interface +- Update rate: 1Hz (default) +- Position accuracy: 2.5m +- Default baud rate: 9600bps + +### Wiring Guide + +#### NEO-6M GPS Connection +| NEO-6M Pin | ESP32 Pin | Description | +|------------|-----------|-------------| +| VCC | 3.3V | Power | +| GND | GND | Ground | +| TX | GPIO16* | UART RX | +| RX | GPIO17* | UART TX | + +#### TFT Display Connection (SPI) +| TFT Pin | ESP32 Pin | Description | +|---------|-----------|-----------------| +| VCC | 3.3V | Power | +| GND | GND | Ground | +| SCL | GPIO18 | SPI Clock | +| SDA | GPIO23 | MOSI | +| RES | GPIO21 | Reset | +| DC | GPIO22 | Data/Command | +| CS | GPIO5 | Chip Select | +| BLK | GPIO4 | Backlight | + +*Note: GPIO pins are configurable in the software \ No newline at end of file diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..112ec3f --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + embuild::espidf::sysenv::output(); +} diff --git a/config/display_config.toml b/config/display_config.toml new file mode 100644 index 0000000..8769c19 --- /dev/null +++ b/config/display_config.toml @@ -0,0 +1,35 @@ +# Display Configuration + +[tft] +# Hardware Configuration +width = 128 +height = 160 +rotation = 0 # 0, 90, 180, or 270 degrees + +# SPI Configuration +spi_clock_speed = 20000000 # 20MHz +spi_mode = 0 + +# Pin Assignments +mosi_pin = 23 +sclk_pin = 18 +cs_pin = 5 +dc_pin = 22 +rst_pin = 21 +blk_pin = 4 + +# Display Settings +default_brightness = 255 # 0-255 +refresh_rate = 1000 # ms +timeout = 30000 # Screen timeout in ms, 0 for always on + +# UI Settings +font_size = 2 +text_color = 0xFFFF # White +background_color = 0x0000 # Black +alert_color = 0xF800 # Red + +# Power Management +enable_power_save = false +dim_timeout = 10000 # ms before dimming +power_save_brightness = 64 # 0-255 diff --git a/config/gps_config.toml b/config/gps_config.toml new file mode 100644 index 0000000..57994b7 --- /dev/null +++ b/config/gps_config.toml @@ -0,0 +1,19 @@ +# GPS Module Configuration + +[neo6m] +# UART Configuration +uart_num = 1 +baud_rate = 9600 +tx_pin = 17 +rx_pin = 16 + +# GPS Settings +update_rate = 1000 # ms +min_satellites = 4 # Minimum satellites for valid fix + +# Anchor Alarm Settings +default_radius = 50 # meters +alarm_check_interval = 5000 # ms + +# Power Management +power_save_mode = false # Future implementation diff --git a/docs/NEO-6M_SETUP.md b/docs/NEO-6M_SETUP.md new file mode 100644 index 0000000..0864c57 --- /dev/null +++ b/docs/NEO-6M_SETUP.md @@ -0,0 +1,113 @@ +# NEO-6M GPS Module Setup Guide + +## Overview +The NEO-6M is a cost-effective GPS module that provides reliable positioning data for the Aniker anchor alarm system. This guide covers the basic setup and configuration of the NEO-6M with the ESP32. + +## Module Features +- High sensitivity: -161 dBm tracking +- Time-To-First-Fix: + - Cold start: 27s + - Hot start: 1s +- Position accuracy: 2.5m CEP (Circular Error Probable) +- Velocity accuracy: 0.1m/s +- Operating temperature: -40°C to 85°C + +## Physical Setup + +### Power Requirements +- Input voltage: 3.3V DC +- Current consumption: ~45mA at continuous operation +- Backup power (optional): 2.0V to 3.6V for faster satellite acquisition + +### Pin Connections +1. **Power Pins** + - VCC → ESP32 3.3V + - GND → ESP32 GND + +2. **Communication Pins** + - TX → ESP32 GPIO16 (RX) + - RX → ESP32 GPIO17 (TX) + +### Antenna Considerations +- The module comes with a ceramic patch antenna +- Place the antenna facing upward with clear view of the sky +- Avoid metal objects directly above the antenna +- Keep antenna away from sources of interference + +## Initial Testing + +### LED Indicators +- Power LED: Should be constantly on +- Signal LED: Will blink when receiving data from satellites + +### Expected Behavior +1. When first powered on, the module will begin searching for satellites +2. Initial position fix may take 30-60 seconds in optimal conditions +3. Signal LED will begin blinking once satellites are acquired + +## Troubleshooting + +### Common Issues + +1. **No Power LED** + - Check 3.3V power connection + - Verify ground connection + - Check for short circuits + +2. **No Signal Reception** + - Ensure clear view of sky + - Check antenna connection + - Move away from sources of interference + - Try outdoor testing first + +3. **Intermittent Data** + - Check wire connections + - Verify baud rate settings + - Check for interference sources + +### Testing Tips +- First test outdoors with clear sky view +- Allow up to 5 minutes for first fix +- Use serial monitor to verify data reception +- Verify correct UART configuration + +## Software Configuration + +### Default Settings +- Baud rate: 9600bps +- Update rate: 1Hz +- NMEA messages: GGA, RMC, GSA, GSV + +### Serial Communication +```rust +// Example configuration in Rust +let config = uart::config::Config { + baudrate: 9600, + data_bits: uart::config::DataBits::DataBits8, + parity: uart::config::Parity::ParityNone, + stop_bits: uart::config::StopBits::STOP1, +}; +``` + +## Performance Expectations + +### Typical Performance +- Time to first fix: 30-60 seconds +- Position accuracy: 2.5m (open sky) +- Update rate: 1Hz +- Operating temperature: -40°C to 85°C + +### Environmental Factors +- Performance degrades under cloud cover +- Indoor operation is not reliable +- Metal objects can cause interference +- Marine environment considerations: + - Salt spray protection needed + - Weatherproofing recommended + - Stable mounting required + +## Future Improvements +- [ ] Add power saving modes +- [ ] Implement faster update rates +- [ ] Add configuration interface +- [ ] Optimize for marine use \ No newline at end of file diff --git a/docs/TFT_SETUP.md b/docs/TFT_SETUP.md new file mode 100644 index 0000000..7c08acb --- /dev/null +++ b/docs/TFT_SETUP.md @@ -0,0 +1,73 @@ +# 1.8" TFT Display Setup Guide + +## Overview +The 1.8" TFT display (128x160) is used as the primary visual interface for the Aniker anchor alarm system. It displays GPS coordinates, anchor status, and alarm conditions. + +## Display Specifications + +### Technical Details +- Display Type: TFT LCD +- Resolution: 128x160 pixels +- Interface: SPI +- Controller: ST7735 (typical) +- Viewing Angle: ~160° +- Operating Voltage: 3.3V +- Backlight: LED +- Color Depth: 16-bit (65K colors) + +### Physical Characteristics +- Screen Size: 1.8 inches diagonal +- Active Area: ~28mm x 35mm +- Module Size: ~34mm x 45mm (approximate) +- Interface: 8-pin connection + +## Hardware Setup + +### Power Requirements +- Logic Voltage: 3.3V +- Current Draw: ~100mA with backlight on +- Backlight Control: PWM capable + +### Pin Connections +1. **Power Pins** + - VCC → ESP32 3.3V + - GND → ESP32 GND + - BLK → ESP32 GPIO4 (Backlight control) + +2. **SPI Interface** + - SCL → ESP32 GPIO18 (SPI Clock) + - SDA → ESP32 GPIO23 (MOSI) + - RES → ESP32 GPIO21 (Reset) + - DC → ESP32 GPIO22 (Data/Command) + - CS → ESP32 GPIO5 (Chip Select) + +### Display Orientation +- The display can be mounted in 4 orientations (0°, 90°, 180°, 270°) +- Software configuration available for orientation adjustment +- Default orientation: Portrait (0°) + +## Software Integration + +### Basic Configuration +```rust +// Example display configuration +let spi = SPIInterface::new( + spi, + gpio23, // MOSI + gpio18, // SCK + gpio5, // CS + gpio22, // DC + gpio21, // RST +); + +let display = ST7735::new( + spi, + gpio4, // BLK + false, // is_inverted + 160, // height + 128, // width +); +``` + +### Display Layout +The screen is organized into several regions: \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..a2f5ab5 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "esp" diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 0000000..c25b89d --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,10 @@ +# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 + +# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). +# This allows to use 1 ms granularity for thread sleeps (10 ms by default). +#CONFIG_FREERTOS_HZ=1000 + +# Workaround for https://github.com/espressif/esp-idf/issues/7631 +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..76a1f51 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,92 @@ +use aniker_gps::{parse_gga, GpsError}; +use esp_idf_svc::hal::delay::FreeRtos; +use log::info; + +const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); + +fn main() { + // Initialize ESP-IDF + esp_idf_svc::sys::link_patches(); + esp_idf_svc::log::EspLogger::initialize_default(); + + info!("Aniker GPS Test Application v{}", APP_VERSION); + info!("----------------------------------------"); + info!("Aniker GPS Test Application Starting..."); + + // Example GPS sentences from different locations around the world: + // 1. Sydney Opera House, Australia + // 2. Mount Everest Base Camp, Nepal + // 3. Machu Picchu, Peru + // 4. Eiffel Tower, Paris, France + // 5. Table Mountain, Cape Town, South Africa + let test_sentences = vec![ + // Sydney Opera House + "$GPGGA,023000,3357.3845,S,15112.7983,E,1,08,1.1,5.0,M,39.2,M,,*6D", + // Mount Everest Base Camp + "$GPGGA,023100,2759.1333,N,08656.9568,E,1,09,1.0,5364.0,M,-95.1,M,,*51", + // Machu Picchu + "$GPGGA,023200,1308.9511,S,07210.9327,W,1,07,1.2,2430.0,M,-15.3,M,,*62", + // Eiffel Tower + "$GPGGA,023300,4851.5156,N,00220.2978,E,1,10,0.9,33.0,M,47.0,M,,*68", + // Table Mountain + "$GPGGA,023400,3357.2828,S,01825.3214,E,1,08,1.0,1085.0,M,-33.0,M,,*6C", + ]; + + // Process each test sentence + for (i, sentence) in test_sentences.iter().enumerate() { + let mut sentence = sentence.to_string(); + + info!("Processing location {}", i + 1); + info!("Raw NMEA: {}", sentence); + + match parse_gga(&mut sentence) { + Ok(position) => { + info!("Successfully parsed GPS data:"); + info!( + " Latitude: {} {}", + position.lat.abs(), + if position.lat >= 0.0 { "N" } else { "S" } + ); + info!( + " Longitude: {} {}", + position.long.abs(), + if position.long >= 0.0 { "E" } else { "W" } + ); + info!(" Altitude: {:.1} meters", position.alt); + + // Add a descriptive location name + let location = match i { + 0 => "Sydney Opera House, Australia", + 1 => "Mount Everest Base Camp, Nepal", + 2 => "Machu Picchu, Peru", + 3 => "Eiffel Tower, Paris, France", + 4 => "Table Mountain, Cape Town, South Africa", + _ => "Unknown Location", + }; + info!(" Location: {}", location); + } + Err(e) => { + info!("Error parsing GPS data:"); + match e { + GpsError::InvalidMessageType => { + info!(" Invalid message type, expected GGA") + } + GpsError::InvalidLength => info!(" Invalid GGA sentence length"), + GpsError::ParseError(msg) => info!(" Parse error: {}", msg), + GpsError::Other(msg) => info!(" Other error: {}", msg), + } + } + } + + info!("----------------------------------------"); + // Add a small delay between processing sentences + FreeRtos::delay_ms(2000); + } + + info!("Aniker GPS Test Application Complete"); + + // Keep the application running + loop { + FreeRtos::delay_ms(1000); + } +}