Skip to content
/ map_tiles Public

Map tiles component for LVGL 9.x - Load and display map tiles with GPS coordinate conversion

License

Notifications You must be signed in to change notification settings

0015/map_tiles

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Map Tiles Component for LVGL 9.x

A comprehensive map tiles component for ESP-IDF projects using LVGL 9.x. This component provides functionality to load and display map tiles with GPS coordinate conversion, designed for embedded applications requiring offline map display capabilities.

Features

  • LVGL 9.x Compatible: Fully compatible with LVGL 9.x image handling
  • GPS Coordinate Conversion: Convert GPS coordinates to tile coordinates and vice versa
  • Dynamic Tile Loading: Load map tiles on demand from file system
  • Configurable Grid Size: Support for different grid sizes (3x3, 5x5, 7x7, etc.)
  • Multiple Tile Types: Support for up to 8 different tile types (street, satellite, terrain, hybrid, etc.)
  • Memory Efficient: Configurable memory allocation (SPIRAM or regular RAM)
  • Multiple Zoom Levels: Support for different map zoom levels
  • Error Handling: Comprehensive error handling and logging
  • C API: Clean C API for easy integration

Requirements

  • ESP-IDF 5.0 or later
  • LVGL 9.3
  • File system support (FAT/SPIFFS/LittleFS)
  • Map tiles in binary format (RGB565, 256x256 pixels)

Installation

Using ESP-IDF Component Manager

You can easily add this component to your project using the idf.py command or by manually updating your idf_component.yml file.

Option 1: Using the idf.py add-dependency command (Recommended)

From your project's root directory, simply run the following command in your terminal:

idf.py add-dependency "0015/map_tiles^1.2.0"

This command will automatically add the component to your idf_component.yml file and download the required files the next time you build your project.

Option 2: Manual idf_component.yml update

Add to your project's main/idf_component.yml:

dependencies:
  map_tiles:
    git: "https://github.com/0015/map_tiles.git"
    version: "^1.2.0"

Manual Installation

  1. Copy the map_tiles folder to your project's components directory
  2. The component will be automatically included in your build

Usage

Basic Setup

#include "map_tiles.h"

// Configure the map tiles with multiple tile types and custom grid size
const char* tile_folders[] = {"street_map", "satellite", "terrain", "hybrid"};
map_tiles_config_t config = {
    .base_path = "/sdcard",                    // Base path to tile storage
    .tile_folders = {tile_folders[0], tile_folders[1], tile_folders[2], tile_folders[3]},
    .tile_type_count = 4,                      // Number of tile types
    .default_zoom = 10,                        // Default zoom level
    .use_spiram = true,                       // Use SPIRAM if available
    .default_tile_type = 0,                   // Start with street map (index 0)
    .grid_cols = 5,                           // Grid width (tiles)
    .grid_rows = 5                            // Grid height (tiles)
};

// Initialize map tiles
map_tiles_handle_t map_handle = map_tiles_init(&config);
if (!map_handle) {
    ESP_LOGE(TAG, "Failed to initialize map tiles");
    return;
}

Loading Tiles

// Set center position from GPS coordinates
map_tiles_set_center_from_gps(map_handle, 37.7749, -122.4194); // San Francisco

// Get grid dimensions
int grid_cols, grid_rows;
map_tiles_get_grid_size(map_handle, &grid_cols, &grid_rows);
int tile_count = map_tiles_get_tile_count(map_handle);

// Load tiles for the configured grid size
for (int row = 0; row < grid_rows; row++) {
    for (int col = 0; col < grid_cols; col++) {
        int index = row * grid_cols + col;
        int tile_x, tile_y;
        map_tiles_get_position(map_handle, &tile_x, &tile_y);
        
        bool loaded = map_tiles_load_tile(map_handle, index, 
                                         tile_x + col, tile_y + row);
        if (!loaded) {
            ESP_LOGW(TAG, "Failed to load tile %d", index);
        }
    }
}

Displaying Tiles with LVGL

// Get grid dimensions and tile count
int grid_cols, grid_rows;
map_tiles_get_grid_size(map_handle, &grid_cols, &grid_rows);
int tile_count = map_tiles_get_tile_count(map_handle);

// Create image widgets for each tile
lv_obj_t** tile_images = malloc(tile_count * sizeof(lv_obj_t*));

for (int i = 0; i < tile_count; i++) {
    tile_images[i] = lv_image_create(parent_container);
    
    // Get the tile image descriptor
    lv_image_dsc_t* img_dsc = map_tiles_get_image(map_handle, i);
    if (img_dsc) {
        lv_image_set_src(tile_images[i], img_dsc);
        
        // Position the tile in the grid
        int row = i / grid_cols;
        int col = i % grid_cols;
        lv_obj_set_pos(tile_images[i], 
                      col * MAP_TILES_TILE_SIZE, 
                      row * MAP_TILES_TILE_SIZE);
    }
}

Switching Tile Types

// Switch to different tile types
map_tiles_set_tile_type(map_handle, 0);  // Street map
map_tiles_set_tile_type(map_handle, 1);  // Satellite
map_tiles_set_tile_type(map_handle, 2);  // Terrain
map_tiles_set_tile_type(map_handle, 3);  // Hybrid

// Get current tile type
int current_type = map_tiles_get_tile_type(map_handle);

// Get available tile types
int type_count = map_tiles_get_tile_type_count(map_handle);
for (int i = 0; i < type_count; i++) {
    const char* folder = map_tiles_get_tile_type_folder(map_handle, i);
    printf("Tile type %d: %s\n", i, folder);
}

GPS Coordinate Conversion

// Convert GPS to tile coordinates
double tile_x, tile_y;
map_tiles_gps_to_tile_xy(map_handle, 37.7749, -122.4194, &tile_x, &tile_y);

// Check if GPS position is within current tile grid
bool within_tiles = map_tiles_is_gps_within_tiles(map_handle, 37.7749, -122.4194);

// Get marker offset for precise positioning
int offset_x, offset_y;
map_tiles_get_marker_offset(map_handle, &offset_x, &offset_y);

Memory Management

// Clean up when done
map_tiles_cleanup(map_handle);

Tile File Format

The component expects map tiles in a specific binary format:

  • File Structure: {base_path}/{map_tile}/{zoom}/{tile_x}/{tile_y}.bin
  • Format: 12-byte header + raw RGB565 pixel data
  • Size: 256x256 pixels
  • Color Format: RGB565 (16-bit per pixel)

Example Tile Structure

/sdcard/
├── street_map/       // Tile type 0
│   ├── 10/
│   │   ├── 164/
│   │   │   ├── 395.bin
│   │   │   ├── 396.bin
│   │   │   └── ...
│   │   └── ...
│   └── ...
├── satellite/        // Tile type 1
│   ├── 10/
│   │   ├── 164/
│   │   │   ├── 395.bin
│   │   │   └── ...
│   │   └── ...
│   └── ...
├── terrain/          // Tile type 2
│   └── ...
└── hybrid/           // Tile type 3
    └── ...

Configuration Options

Parameter Type Description Default
base_path const char* Base directory for tile storage Required
tile_folders const char*[] Array of folder names for different tile types Required
tile_type_count int Number of tile types (max 8) Required
default_zoom int Initial zoom level Required
use_spiram bool Use SPIRAM for tile buffers false
default_tile_type int Initial tile type index Required
grid_cols int Number of tile columns (max 10) 5
grid_rows int Number of tile rows (max 10) 5

API Reference

Initialization

  • map_tiles_init() - Initialize map tiles system
  • map_tiles_cleanup() - Clean up resources

Tile Management

  • map_tiles_load_tile() - Load a specific tile
  • map_tiles_get_image() - Get LVGL image descriptor
  • map_tiles_get_buffer() - Get raw tile buffer

Grid Management

  • map_tiles_get_grid_size() - Get current grid dimensions
  • map_tiles_get_tile_count() - Get total number of tiles in grid

Coordinate Conversion

  • map_tiles_gps_to_tile_xy() - Convert GPS to tile coordinates
  • map_tiles_set_center_from_gps() - Set center from GPS
  • map_tiles_is_gps_within_tiles() - Check if GPS is within current tiles

Position Management

  • map_tiles_get_position() - Get current tile position
  • map_tiles_set_position() - Set tile position
  • map_tiles_get_marker_offset() - Get marker offset
  • map_tiles_set_marker_offset() - Set marker offset

Tile Type Management

  • map_tiles_set_tile_type() - Set active tile type
  • map_tiles_get_tile_type() - Get current tile type
  • map_tiles_get_tile_type_count() - Get number of available types
  • map_tiles_get_tile_type_folder() - Get folder name for a type

Zoom Control

  • map_tiles_set_zoom() - Set zoom level
  • map_tiles_get_zoom() - Get current zoom level

Error Handling

  • map_tiles_set_loading_error() - Set error state
  • map_tiles_has_loading_error() - Check error state

Performance Considerations

  • Memory Usage: Each tile uses ~128KB (256×256×2 bytes)
  • Grid Size: Larger grids use more memory (3x3=9 tiles, 5x5=25 tiles, 7x7=49 tiles)
  • SPIRAM: Recommended for ESP32-S3 with PSRAM for better performance
  • File System: Ensure adequate file system performance for tile loading
  • Tile Caching: Component maintains tile buffers until cleanup

Example Projects

See the examples directory for complete implementation examples:

  • Basic map display
  • GPS tracking with map updates
  • Interactive map with touch controls

License

This component is released under the MIT License. See LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.

Support

For questions and support, please open an issue on the GitHub repository.

About

Map tiles component for LVGL 9.x - Load and display map tiles with GPS coordinate conversion

Topics

Resources

License

Stars

Watchers

Forks