Carregar ficheiros para "src/core"

This commit is contained in:
2024-12-19 09:20:26 -08:00
parent ab8f1cb349
commit 16f68bd726
5 changed files with 914 additions and 0 deletions

1
src/core/__init__.py Normal file
View File

@ -0,0 +1 @@

118
src/core/command.py Normal file
View File

@ -0,0 +1,118 @@
from abc import ABC, abstractmethod
from typing import List, Tuple, Any
import numpy as np
from .file_handler import MapData
class Command(ABC):
@abstractmethod
def execute(self) -> bool:
pass
@abstractmethod
def undo(self) -> bool:
pass
class MapValueCommand(Command):
"""Command for single value changes in a map"""
def __init__(self, map_data: MapData, x: int, y: int, new_value: float):
self.map_data = map_data
self.x = x
self.y = y
self.new_value = new_value
self.old_value = map_data.data[x, y]
def execute(self) -> bool:
try:
self.map_data.data[self.x, self.y] = self.new_value
self.map_data.modified = True
return True
except Exception:
return False
def undo(self) -> bool:
try:
self.map_data.data[self.x, self.y] = self.old_value
self.map_data.modified = True
return True
except Exception:
return False
class RegionCommand(Command):
"""Command for region modifications"""
def __init__(self, map_data: MapData, x1: int, y1: int, x2: int, y2: int,
new_values: np.ndarray):
self.map_data = map_data
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
self.new_values = new_values
self.old_values = map_data.data[x1:x2+1, y1:y2+1].copy()
def execute(self) -> bool:
try:
self.map_data.data[self.x1:self.x2+1, self.y1:self.y2+1] = self.new_values
self.map_data.modified = True
return True
except Exception:
return False
def undo(self) -> bool:
try:
self.map_data.data[self.x1:self.x2+1, self.y1:self.y2+1] = self.old_values
self.map_data.modified = True
return True
except Exception:
return False
class CommandHistory:
def __init__(self, max_history: int = 50):
self.max_history = max_history
self.history: List[Command] = []
self.current: int = -1
def execute(self, command: Command) -> bool:
"""Execute a new command and add it to history"""
if command.execute():
# Remove any undone commands
if self.current < len(self.history) - 1:
self.history = self.history[:self.current + 1]
self.history.append(command)
self.current += 1
# Limit history size
if len(self.history) > self.max_history:
self.history = self.history[-self.max_history:]
self.current = len(self.history) - 1
return True
return False
def undo(self) -> bool:
"""Undo the last command"""
if self.can_undo():
if self.history[self.current].undo():
self.current -= 1
return True
return False
def redo(self) -> bool:
"""Redo the last undone command"""
if self.can_redo():
self.current += 1
return self.history[self.current].execute()
return False
def can_undo(self) -> bool:
"""Check if undo is possible"""
return self.current >= 0
def can_redo(self) -> bool:
"""Check if redo is possible"""
return self.current < len(self.history) - 1
def clear(self):
"""Clear command history"""
self.history.clear()
self.current = -1

View File

@ -0,0 +1,160 @@
from typing import Dict, List
from dataclasses import dataclass
@dataclass
class MapAxis:
name: str
values: List[float]
units: str
@dataclass
class EDC15MapInfo:
name: str
address: int
rows: int
cols: int
value_type: str
description: str
x_axis: MapAxis
y_axis: MapAxis
units: str
# Common EDC15 map definitions
EDC15_MAPS = {
# Fuel Maps
"MAIN_FUEL_MAP": EDC15MapInfo(
name="Mapa Principal de Combustível",
address=0x4000, # Example address
rows=16,
cols=16,
value_type="float32",
description="Mapa principal de injeção de combustível",
x_axis=MapAxis("RPM", [800, 1000, 1500, 2000, 2500, 3000, 3500, 4000,
4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000],
"rpm"),
y_axis=MapAxis("Load", [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
110, 120, 130, 140, 150],
"%"),
units="mg/stroke"
),
"PILOT_INJECTION": EDC15MapInfo(
name="Mapa de Pré-Injeção",
address=0x4400, # Example address
rows=12,
cols=12,
value_type="float32",
description="Mapa de controle da pré-injeção",
x_axis=MapAxis("RPM", [800, 1200, 1600, 2000, 2400, 2800, 3200, 3600,
4000, 4400, 4800, 5200],
"rpm"),
y_axis=MapAxis("Load", [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165],
"%"),
units="mg/stroke"
),
# Boost Maps
"BOOST_CONTROL": EDC15MapInfo(
name="Mapa de Controle de Boost",
address=0x4800, # Example address
rows=16,
cols=12,
value_type="float32",
description="Mapa de controle de pressão do turbo",
x_axis=MapAxis("RPM", [1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500,
5000, 5500, 6000, 6500],
"rpm"),
y_axis=MapAxis("Load", [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
110, 120, 130, 140, 150],
"%"),
units="mbar"
),
# Timing Maps
"INJECTION_TIMING": EDC15MapInfo(
name="Mapa de Avanço de Injeção",
address=0x4C00, # Example address
rows=16,
cols=16,
value_type="float32",
description="Mapa de avanço do ponto de injeção",
x_axis=MapAxis("RPM", [800, 1000, 1500, 2000, 2500, 3000, 3500, 4000,
4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000],
"rpm"),
y_axis=MapAxis("Load", [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100,
110, 120, 130, 140, 150],
"%"),
units="degrees"
),
# EGR Maps
"EGR_CONTROL": EDC15MapInfo(
name="Mapa de Controle EGR",
address=0x5000, # Example address
rows=12,
cols=12,
value_type="float32",
description="Mapa de controle da válvula EGR",
x_axis=MapAxis("RPM", [800, 1200, 1600, 2000, 2400, 2800, 3200, 3600,
4000, 4400, 4800, 5200],
"rpm"),
y_axis=MapAxis("Load", [0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165],
"%"),
units="%"
),
# Limit Maps
"TORQUE_LIMIT": EDC15MapInfo(
name="Mapa de Limite de Torque",
address=0x5400, # Example address
rows=12,
cols=16,
value_type="float32",
description="Mapa de limite de torque do motor",
x_axis=MapAxis("RPM", [800, 1000, 1500, 2000, 2500, 3000, 3500, 4000,
4500, 5000, 5500, 6000, 6500, 7000, 7500, 8000],
"rpm"),
y_axis=MapAxis("Temperature", [0, 20, 40, 60, 70, 75, 80, 85, 90, 95,
100, 105],
"°C"),
units="Nm"
),
}
# Checksum regions
CHECKSUM_REGIONS = [
(0x0000, 0x1000), # Example region 1
(0x4000, 0x6000), # Example region 2
]
# Known file signatures
EDC15_SIGNATURES = {
"EDC15P": bytes([0x55, 0xAA, 0x55, 0xAA]),
"EDC15V": bytes([0xAA, 0x55, 0xAA, 0x55]),
}
def calculate_checksum(data: bytes, start: int, end: int) -> int:
"""Calculate checksum for a region of data"""
checksum = 0
for i in range(start, end):
if i < len(data):
checksum = (checksum + data[i]) & 0xFF
return checksum
def validate_ecu_file(data: bytes) -> bool:
"""Validate EDC15 file format and checksums"""
if len(data) < 0x8000: # Minimum size check
return False
# Check for known signatures
for sig_name, signature in EDC15_SIGNATURES.items():
if data.startswith(signature):
# Verify checksums for each region
for start, end in CHECKSUM_REGIONS:
stored_checksum = data[end] if end < len(data) else 0
calculated = calculate_checksum(data, start, end)
if stored_checksum != calculated:
return False
return True
return False

131
src/core/edc15_maps.py Normal file
View File

@ -0,0 +1,131 @@
from typing import Dict, List, Tuple
import numpy as np
from .file_handler import MapData
class EDC15MapDefinition:
def __init__(self, name: str, address: int, rows: int, cols: int,
value_type: str, description: str = ""):
self.name = name
self.address = address
self.rows = rows
self.cols = cols
self.value_type = value_type # 'uint8', 'uint16', 'float'
self.description = description
class EDC15MapDetector:
# Common EDC15 map signatures
KNOWN_SIGNATURES = {
b'\x00\x00\x80\x3F': 'float32', # 1.0f in IEEE 754
b'\x00\x00\x00\x40': 'float32', # 2.0f in IEEE 754
b'\xCD\xCC\xCC\x3D': 'float32', # 0.1f in IEEE 754
}
# Common map sizes in EDC15
COMMON_SIZES = [(8, 8), (16, 16), (12, 12), (16, 12), (12, 16)]
def __init__(self, data: bytes):
self.data = data
self.size = len(data)
def find_potential_maps(self) -> List[EDC15MapDefinition]:
"""
Find potential maps in the binary data based on known patterns
"""
potential_maps = []
# Search for known signatures
for signature, value_type in self.KNOWN_SIGNATURES.items():
offset = 0
while True:
offset = self.data.find(signature, offset)
if offset == -1:
break
# Check for potential map structure around signature
for rows, cols in self.COMMON_SIZES:
if self._validate_map_structure(offset, rows, cols, value_type):
map_def = EDC15MapDefinition(
f"Map_0x{offset:X}",
offset,
rows,
cols,
value_type
)
potential_maps.append(map_def)
offset += len(signature)
return potential_maps
def _validate_map_structure(self, offset: int, rows: int, cols: int,
value_type: str) -> bool:
"""
Validate if a potential map structure exists at the given offset
"""
# Calculate required space for the map
bytes_per_value = 4 if value_type == 'float32' else 2
required_space = rows * cols * bytes_per_value
# Check if we have enough space in the file
if offset + required_space > self.size:
return False
# Validate data consistency
try:
data = self._extract_map_data(offset, rows, cols, value_type)
# Check for reasonable value ranges
if value_type == 'float32':
if not np.all(np.isfinite(data)):
return False
if np.any(np.abs(data) > 1000000): # Unreasonable values
return False
# Check for patterns that suggest this is actually a map
# 1. Check if values are somewhat continuous
differences = np.abs(np.diff(data.ravel()))
if np.max(differences) > 1000: # Too large jumps between values
return False
# 2. Check if there's some variation (not all same value)
if np.all(data == data[0, 0]):
return False
return True
except Exception:
return False
def _extract_map_data(self, offset: int, rows: int, cols: int,
value_type: str) -> np.ndarray:
"""
Extract map data from binary file
"""
bytes_per_value = 4 if value_type == 'float32' else 2
total_bytes = rows * cols * bytes_per_value
raw_data = self.data[offset:offset + total_bytes]
if value_type == 'float32':
data = np.frombuffer(raw_data, dtype=np.float32)
else:
data = np.frombuffer(raw_data, dtype=np.uint16)
return data.reshape((rows, cols))
def extract_map(self, map_def: EDC15MapDefinition) -> MapData:
"""
Extract map data based on map definition
"""
data = self._extract_map_data(
map_def.address,
map_def.rows,
map_def.cols,
map_def.value_type
)
# Create axis data (placeholder - should be extracted from actual file)
x_axis = np.linspace(0, map_def.cols - 1, map_def.cols)
y_axis = np.linspace(0, map_def.rows - 1, map_def.rows)
return MapData(map_def.name, data, x_axis, y_axis)

504
src/core/edc15p_maps.py Normal file
View File

@ -0,0 +1,504 @@
from dataclasses import dataclass
from typing import Dict, List, Optional
@dataclass
class MapDefinition:
name: str
address: str # Hex address in the binary
rows: int
cols: int
x_axis: List[float]
y_axis: List[float]
description: str
units: str
category: str
group: str
# Map definitions for EDC15P
EDC15P_MAPS = {
# Drivers Wish [FUEL]
"drivers_wish_1": MapDefinition(
name="Drivers Wish Map 1",
address="04D206",
rows=12,
cols=8,
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70], # Load %
description="Drivers Wish Map 1",
units="FUEL",
category="Fuel",
group="Drivers Wish [FUEL]"
),
"drivers_wish_2": MapDefinition(
name="Drivers Wish Map 2",
address="06D206",
rows=12,
cols=8,
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70], # Load %
description="Drivers Wish Map 2",
units="FUEL",
category="Fuel",
group="Drivers Wish [FUEL]"
),
# Torque [FUEL]
"torque_1": MapDefinition(
name="Torque Map 1",
address="04D8D2",
rows=3,
cols=20,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500], # RPM
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95], # Load %
description="Torque Control Map 1",
units="FUEL",
category="Torque",
group="Torque [FUEL]"
),
"torque_2": MapDefinition(
name="Torque Map 2",
address="06D8D2",
rows=3,
cols=20,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500], # RPM
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95], # Load %
description="Torque Control Map 2",
units="FUEL",
category="Torque",
group="Torque [FUEL]"
),
# Smoke Limiter [FUEL]
"smoke_limiter_1": MapDefinition(
name="Smoke Limiter Map 1",
address="04DA04",
rows=16,
cols=13,
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200, 5600], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
description="Smoke Limiter Map 1",
units="FUEL",
category="Limiters",
group="Smoke Limiter [FUEL]"
),
"smoke_limiter_2": MapDefinition(
name="Smoke Limiter Map 2",
address="04DBF6",
rows=16,
cols=13,
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200, 5600], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
description="Smoke Limiter Map 2",
units="FUEL",
category="Limiters",
group="Smoke Limiter [FUEL]"
),
"smoke_limiter_3": MapDefinition(
name="Smoke Limiter Map 3",
address="06DA04",
rows=16,
cols=13,
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200, 5600], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
description="Smoke Limiter Map 3",
units="FUEL",
category="Limiters",
group="Smoke Limiter [FUEL]"
),
"smoke_limiter_4": MapDefinition(
name="Smoke Limiter Map 4",
address="06DBF6",
rows=16,
cols=13,
x_axis=[800, 1200, 1600, 2000, 2400, 2800, 3200, 3600, 4000, 4400, 4800, 5200, 5600], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
description="Smoke Limiter Map 4",
units="FUEL",
category="Limiters",
group="Smoke Limiter [FUEL]"
),
# Speed Limiter Via Temp [ENGINE LOAD]
"speed_temp_limiter_1": MapDefinition(
name="Speed Temperature Limiter 1",
address="04E732",
rows=4,
cols=4,
x_axis=[0, 30, 60, 90], # Temperature
y_axis=[0, 25, 50, 75], # Speed %
description="Speed Limiter via Temperature Map 1",
units="ENGINE LOAD",
category="Limiters",
group="Speed Limiter Via Temp [ENGINE LOAD]"
),
"speed_temp_limiter_2": MapDefinition(
name="Speed Temperature Limiter 2",
address="06E732",
rows=4,
cols=4,
x_axis=[0, 30, 60, 90], # Temperature
y_axis=[0, 25, 50, 75], # Speed %
description="Speed Limiter via Temperature Map 2",
units="ENGINE LOAD",
category="Limiters",
group="Speed Limiter Via Temp [ENGINE LOAD]"
),
# Injection Limiter Via Temp [LOAD]
"injection_temp_limiter_1": MapDefinition(
name="Injection Temperature Limiter 1",
address="04F238",
rows=3,
cols=3,
x_axis=[0, 50, 100], # Temperature
y_axis=[0, 50, 100], # Load %
description="Injection Limiter via Temperature Map 1",
units="LOAD",
category="Limiters",
group="Injection Limiter Via Temp [LOAD]"
),
"injection_temp_limiter_2": MapDefinition(
name="Injection Temperature Limiter 2",
address="06F238",
rows=3,
cols=3,
x_axis=[0, 50, 100], # Temperature
y_axis=[0, 50, 100], # Load %
description="Injection Limiter via Temperature Map 2",
units="LOAD",
category="Limiters",
group="Injection Limiter Via Temp [LOAD]"
),
# Boost Limiter Via Temperature [mBAR]
"boost_temp_limiter_1": MapDefinition(
name="Boost Temperature Limiter 1",
address="051FA0",
rows=16,
cols=10,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
y_axis=[0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300], # Temperature
description="Boost Limiter via Temperature Map 1",
units="mBAR",
category="Limiters",
group="Boost Limiter Via Temperature [mBAR]"
),
"boost_temp_limiter_2": MapDefinition(
name="Boost Temperature Limiter 2",
address="071FA0",
rows=16,
cols=10,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
y_axis=[0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300], # Temperature
description="Boost Limiter via Temperature Map 2",
units="mBAR",
category="Limiters",
group="Boost Limiter Via Temperature [mBAR]"
),
# Spraying Time [DEG]
"spraying_time_1": MapDefinition(
name="Spraying Time Map 1",
address="054548",
rows=10,
cols=10,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90], # Load %
description="Spraying Time Map 1",
units="DEG",
category="Timing",
group="Spraying Time [DEG]"
),
"spraying_time_2": MapDefinition(
name="Spraying Time Map 2",
address="05465C",
rows=15,
cols=19,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
description="Spraying Time Map 2",
units="DEG",
category="Timing",
group="Spraying Time [DEG]"
),
"spraying_time_3": MapDefinition(
name="Spraying Time Map 3",
address="0548E2",
rows=15,
cols=19,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
description="Spraying Time Map 3",
units="DEG",
category="Timing",
group="Spraying Time [DEG]"
),
"spraying_time_4": MapDefinition(
name="Spraying Time Map 4",
address="054B68",
rows=15,
cols=19,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
description="Spraying Time Map 4",
units="DEG",
category="Timing",
group="Spraying Time [DEG]"
),
"spraying_time_5": MapDefinition(
name="Spraying Time Map 5",
address="074548",
rows=10,
cols=10,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90], # Load %
description="Spraying Time Map 5",
units="DEG",
category="Timing",
group="Spraying Time [DEG]"
),
"spraying_time_6": MapDefinition(
name="Spraying Time Map 6",
address="07465C",
rows=15,
cols=19,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
description="Spraying Time Map 6",
units="DEG",
category="Timing",
group="Spraying Time [DEG]"
),
"spraying_time_7": MapDefinition(
name="Spraying Time Map 7",
address="0748E2",
rows=15,
cols=19,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
description="Spraying Time Map 7",
units="DEG",
category="Timing",
group="Spraying Time [DEG]"
),
"spraying_time_8": MapDefinition(
name="Spraying Time Map 8",
address="074B68",
rows=15,
cols=19,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500, 7000], # RPM
y_axis=[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90], # Load %
description="Spraying Time Map 8",
units="DEG",
category="Timing",
group="Spraying Time [DEG]"
),
# Air Mass Substitutive value [FUEL]
"air_mass_sub_1": MapDefinition(
name="Air Mass Substitutive Value 1",
address="055632",
rows=8,
cols=8,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70], # Load %
description="Air Mass Substitutive Value Map 1",
units="FUEL",
category="Air Mass",
group="Air Mass Substitutive value [FUEL]"
),
"air_mass_sub_2": MapDefinition(
name="Air Mass Substitutive Value 2",
address="075632",
rows=8,
cols=8,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70], # Load %
description="Air Mass Substitutive Value Map 2",
units="FUEL",
category="Air Mass",
group="Air Mass Substitutive value [FUEL]"
),
# Boost Pressure [mBAR]
"boost_pressure_1": MapDefinition(
name="Boost Pressure Map 1",
address="056926",
rows=16,
cols=10,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
description="Boost Pressure Control Map 1",
units="mBAR",
category="Boost",
group="Boost Pressure [mBAR]"
),
"boost_pressure_2": MapDefinition(
name="Boost Pressure Map 2",
address="076926",
rows=16,
cols=10,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150], # Load %
description="Boost Pressure Control Map 2",
units="mBAR",
category="Boost",
group="Boost Pressure [mBAR]"
),
# Boost Limiter Via Patm [mBAR]
"boost_patm_limiter_1": MapDefinition(
name="Boost Patm Limiter 1",
address="056F1C",
rows=10,
cols=10,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
y_axis=[800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250], # Atmospheric Pressure
description="Boost Limiter via Atmospheric Pressure Map 1",
units="mBAR",
category="Limiters",
group="Boost Limiter Via Patm [mBAR]"
),
"boost_patm_limiter_2": MapDefinition(
name="Boost Patm Limiter 2",
address="076F1C",
rows=10,
cols=10,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500], # RPM
y_axis=[800, 850, 900, 950, 1000, 1050, 1100, 1150, 1200, 1250], # Atmospheric Pressure
description="Boost Limiter via Atmospheric Pressure Map 2",
units="mBAR",
category="Limiters",
group="Boost Limiter Via Patm [mBAR]"
),
# Advance Limiter Via Temp [DEG]
"advance_temp_limiter_1": MapDefinition(
name="Advance Temperature Limiter 1",
address="0581B6",
rows=14,
cols=11,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130], # Temperature
description="Advance Limiter via Temperature Map 1",
units="DEG",
category="Limiters",
group="Advance Limiter Via Temp [DEG]"
),
"advance_temp_limiter_2": MapDefinition(
name="Advance Temperature Limiter 2",
address="0781B6",
rows=14,
cols=11,
x_axis=[0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000, 4500, 5000], # RPM
y_axis=[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130], # Temperature
description="Advance Limiter via Temperature Map 2",
units="DEG",
category="Limiters",
group="Advance Limiter Via Temp [DEG]"
),
# Idle Speed [RPM]
"idle_speed_1": MapDefinition(
name="Idle Speed Control 1",
address="056FEC",
rows=1,
cols=2,
x_axis=[0], # No X axis (single column)
y_axis=[0, 1], # Two states
description="Idle Speed Control Map 1",
units="RPM",
category="Speed",
group="Idle Speed [RPM]"
),
# Maximum Boost Pressure [mBAR]
"max_boost_pressure_1": MapDefinition(
name="Maximum Boost Pressure 1",
address="051C84",
rows=1,
cols=1,
x_axis=[0], # Single value
y_axis=[0], # Single value
description="Maximum Boost Pressure Map 1",
units="mBAR",
category="Limiters",
group="Maximum Boost Pressure [mBAR]"
),
"max_boost_pressure_2": MapDefinition(
name="Maximum Boost Pressure 2",
address="071C84",
rows=1,
cols=1,
x_axis=[0], # Single value
y_axis=[0], # Single value
description="Maximum Boost Pressure Map 2",
units="mBAR",
category="Limiters",
group="Maximum Boost Pressure [mBAR]"
),
# Maximum RPM Limiter [RPM]
"max_rpm_limiter_1": MapDefinition(
name="Maximum RPM Limiter 1",
address="0541A3",
rows=1,
cols=1,
x_axis=[0], # Single value
y_axis=[0], # Single value
description="Maximum RPM Limiter Map 1",
units="RPM",
category="Limiters",
group="Maximum RPM Limiter [RPM]"
),
"max_rpm_limiter_2": MapDefinition(
name="Maximum RPM Limiter 2",
address="0741A3",
rows=1,
cols=1,
x_axis=[0], # Single value
y_axis=[0], # Single value
description="Maximum RPM Limiter Map 2",
units="RPM",
category="Limiters",
group="Maximum RPM Limiter [RPM]"
)
}
def get_map_definition(map_id: str) -> Optional[MapDefinition]:
"""Get map definition by ID"""
return EDC15P_MAPS.get(map_id)
def list_maps() -> List[str]:
"""List all available map IDs"""
return list(EDC15P_MAPS.keys())
def list_maps_by_group() -> Dict[str, List[MapDefinition]]:
"""List maps grouped by their groups"""
groups: Dict[str, List[MapDefinition]] = {}
# First pass: collect all unique groups
for map_def in EDC15P_MAPS.values():
if map_def.group not in groups:
groups[map_def.group] = []
# Second pass: add maps to their groups
for map_id, map_def in EDC15P_MAPS.items():
groups[map_def.group].append(map_def)
return groups
def list_maps_by_category() -> Dict[str, List[MapDefinition]]:
"""List maps grouped by category"""
categories: Dict[str, List[MapDefinition]] = {}
# First pass: collect all unique categories
for map_def in EDC15P_MAPS.values():
if map_def.category not in categories:
categories[map_def.category] = []
# Second pass: add maps to their categories
for map_id, map_def in EDC15P_MAPS.items():
categories[map_def.category].append(map_def)
return categories