# 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 Add to your project's `main/idf_component.yml`: ```yaml dependencies: map_tiles: git: "https://github.com/0015/map_tiles.git" version: "^1.1.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 ```c #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 ```c // 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 ```c // 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 ```c // 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 ```c // 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 ```c // 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.
idf.py add-dependency "0015/map_tiles^1.1.0"