Initial commit

This commit is contained in:
2025-10-22 20:40:25 +03:00
commit 63d038ee63
57 changed files with 104378 additions and 0 deletions

17
.editorconfig Normal file
View File

@@ -0,0 +1,17 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = false
[*.{h,cpp,json,sh,bat,ps1,ld}]
indent_style = tab
indent_size = 4
[*.py]
indent_style = space
indent_size = 2

View File

@@ -0,0 +1,4 @@
## Actions
* `push-branch.yaml` - Тестовая сборка при пуше веток.
* `push-release-tag.yaml` - Сборка релиза и загрузка черновика со всеми файлами при пуше тэга релиза.

View File

@@ -0,0 +1,56 @@
# https://docs.gitea.com/usage/actions/overview
# https://github.com/marketplace?type=actions
# https://gitea.com/actions
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
name: Push Branch
on:
push:
branches:
- '**'
jobs:
Build_Test:
name: Build Test
runs-on: ubuntu-latest
steps:
# https://github.com/actions/checkout
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Dev Tools Cache
uses: actions/cache@v3
with:
path: |
~/.xpack-dev-tools
/usr/bin/xxd
/usr/bin/srec_cat
/lib/x86_64-linux-gnu/libsrecord.so.0.0.0
/lib/x86_64-linux-gnu/libsrecord.so.0
key: ${{ runner.os }}-xpack-dev-tools-xxd-srecord
- name: Dev Tools install
run: sys/install.sh
- name: Build M2 Debug
if: success() || failure()
run: . sys/export.sh; make -e MODEL=M2 debug
- name: Build M2 Release
if: success() || failure()
run: . sys/export.sh; make -e MODEL=M2 release
- name: Build M3 Debug
if: success() || failure()
run: . sys/export.sh; make -e MODEL=M3 debug
- name: Build M3 Release
if: success() || failure()
run: . sys/export.sh; make -e MODEL=M3 release
- name: Changelog
if: success() || failure()
run: sys/changelog.sh; cat CHANGELOG.md

View File

@@ -0,0 +1,73 @@
# https://docs.gitea.com/usage/actions/overview
# https://github.com/marketplace?type=actions
# https://gitea.com/actions
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
name: Push Release Tag
on:
push:
tags:
- 'v*'
- '*_v*'
jobs:
Build_and_draft_Release_tag:
name: Build Release and Draft
runs-on: ubuntu-latest
steps:
# https://github.com/actions/checkout
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: Dev Tools Cache
uses: actions/cache@v3
with:
path: |
~/.xpack-dev-tools
/usr/bin/xxd
/usr/bin/srec_cat
/lib/x86_64-linux-gnu/libsrecord.so.0.0.0
/lib/x86_64-linux-gnu/libsrecord.so.0
key: ${{ runner.os }}-xpack-dev-tools-xxd-srecord
- name: Dev Tools install
run: sys/install.sh
- name: Build M2 Release
id: M2
if: success() || failure()
run: . sys/export.sh; make -e MODEL=M2 release
- name: Build M3 Release
id: M3
if: success() || failure()
run: . sys/export.sh; make -e MODEL=M3 release
- name: Changelog
if: success() || failure()
run: sys/changelog.sh; cat CHANGELOG.md
# https://github.com/actions/setup-node
- name: Node setup
# https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#steps-context
if: ( ${{ success() }} || ${{ failure() }} ) && ( ${{ steps.M2.outcome }} == 'success' || ${{ steps.M3.outcome }} == 'success' )
uses: actions/setup-node@v4
with:
node-version: 18
# https://github.com/akkuman/gitea-release-action
- name: Upload Draft Release
if: ( ${{ success() }} || ${{ failure() }} ) && ( ${{ steps.M2.outcome }} == 'success' || ${{ steps.M3.outcome }} == 'success' )
uses: akkuman/gitea-release-action@v1
with:
token: '${{secrets.ACTION_TOKEN}}'
body: 'Описание релиза'
body_path: 'CHANGELOG.md'
draft: true
prerelease: true
files: |-
build/M2_Release/*.fw
build/M3_Release/*.fw

12
.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
/build
/CHANGELOG.md
/libs/Version.h
/.vscode/*
!/.vscode/c_cpp_properties.json
!/.vscode/extensions.json
!/.vscode/launch.json
!/.vscode/settings.json
!/.vscode/tasks.json
sys/__pycache__/

41
.vscode/c_cpp_properties.json vendored Normal file
View File

@@ -0,0 +1,41 @@
{
"configurations": [
{
"name": "M2",
"intelliSenseMode": "gcc-arm",
"cStandard": "c17",
"cppStandard": "c++17",
"includePath": [
"libs",
"src"
],
"defines": [
"DEBUG",
"STM32F10X_CL",
"HSE_VALUE=16000000",
"CAN_FIRMWARE=1",
"MOBICAR_1_2=1"
],
"compilerPath": "${userHome}/.xpack-dev-tools/xpack-arm-none-eabi-gcc-12.3.1-1.2/bin/arm-none-eabi-gcc"
},
{
"name": "M3",
"intelliSenseMode": "gcc-arm",
"cStandard": "c17",
"cppStandard": "c++17",
"includePath": [
"libs",
"src"
],
"defines": [
"DEBUG",
"STM32F10X_CL",
"HSE_VALUE=16000000",
"CAN_FIRMWARE=1",
"MOBICAR_3=1"
],
"compilerPath": "${userHome}/.xpack-dev-tools/xpack-arm-none-eabi-gcc-12.3.1-1.2/bin/arm-none-eabi-gcc"
}
],
"version": 4
}

18
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,18 @@
{
"recommendations": [
/* mandatory extensions */
"ms-vscode.cpptools", // C/C++ support
"marus25.cortex-debug", // Cortex-Debug
/* handy extensions (optional) */
"spencerwmiles.vscode-task-buttons",// Run tasks using statusbar buttons
"mhutchie.git-graph", // Git Graph
"pkief.material-icon-theme", // Icons
"ZixuanWang.linkerscript", // Linker Script files syntax
"trond-snekvik.gnu-mapfiles", // Linker Map files syntax
"keroc.hex-fmt", // Intel Hex files syntax
"ms-vscode.hexeditor", // Hex editor for binary files
"dan-c-underwood.arm", // ARM Assembly files syntax
"EditorConfig.EditorConfig", // editorconfig
"YuTengjing.open-in-external-app", // Open files in external app
]
}

106
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,106 @@
{
"configurations": [
{
"name": "Debug M2",
"request": "launch",
"preLaunchTask": "Build M2 Debug",
"executable": "./build/M2_Debug/CAN_FW.elf",
"cwd": "${workspaceRoot}",
"showDevDebugOutput": "parsed",
"type": "cortex-debug",
// J-Link config //
"servertype": "jlink",
"serverArgs": ["-speed", "4000"],
"windows": {
"serverpath": "C:/Program Files/SEGGER/JLink/JLinkGDBServerCL.exe"
},
"osx": {
"serverpath": "/Applications/SEGGER/JLink/JLinkGDBServer"
},
"device": "STM32F105VC",
"svdFile": "sys/STM32F107.svd",
"swoConfig":
{
"enabled": true,
"cpuFrequency": 36000000,
"swoFrequency": 12000000,
"source": "probe",
"decoders":
[
{
"label": "ITM",
"type": "console",
"port": 0,
"showOnStartup": true,
"encoding": "ascii",
}
]
},
// "rttConfig": {
// "enabled": true,
// "address": "auto",
// "decoders": [
// {
// "label": "RTT Log",
// "port": 0,
// "type": "console",
// "noprompt": true,
// }
// ]
// },
// Other //
"internalConsoleOptions": "neverOpen"
},
{
"name": "Debug M3",
"request": "launch",
"preLaunchTask": "Build M3 Debug",
"executable": "./build/M3_Debug/CAN_FW.elf",
"cwd": "${workspaceRoot}",
"showDevDebugOutput": "parsed",
"type": "cortex-debug",
// J-Link config //
"servertype": "jlink",
"serverArgs": ["-speed", "4000"],
"windows": {
"serverpath": "C:/Program Files/SEGGER/JLink/JLinkGDBServerCL.exe"
},
"osx": {
"serverpath": "/Applications/SEGGER/JLink/JLinkGDBServer"
},
"device": "STM32F446ZE",
"svdFile": "sys/STM32F446.svd",
"swoConfig":
{
"enabled": true,
"cpuFrequency": 36000000,
"swoFrequency": 12000000,
"source": "probe",
"decoders":
[
{
"label": "ITM",
"type": "console",
"port": 0,
"showOnStartup": true,
"encoding": "ascii"
}
]
},
// "rttConfig": {
// "enabled": true,
// "address": "auto",
// "decoders": [
// {
// "label": "RTT Log",
// "port": 0,
// "type": "console",
// "noprompt": true,
// }
// ]
// },
// Other //
"internalConsoleOptions": "neverOpen"
}
]
}

114
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,114 @@
{
// Terminal profiles:
"terminal.integrated.profiles.windows": {
"Git Bash": {
"source": "Git Bash",
// "icon": "tools",
"color": "terminal.ansiGreen",
"overrideName": false,
"env": {},
"args": ["--init-file", "sys/export.sh"]
},
"Command Prompt": {
"path": "C:/Windows/System32/cmd.exe",
// "icon": "tools",
"color": "terminal.ansiGreen",
"overrideName": false,
"env": {},
"args": ["/k call sys/export.bat"]
},
"PowerShell": {
"source": "PowerShell",
// "icon": "tools",
"color": "terminal.ansiGreen",
"overrideName": false,
"env": {},
"args": ["-noexit", "-file", "sys/export.ps1"]
}
},
"terminal.integrated.defaultProfile.linux": "Build bash",
"terminal.integrated.profiles.linux": {
"Build bash": {
"path": "bash",
"icon": "terminal-bash",
"color": "terminal.ansiGreen",
"overrideName": true,
"env": {},
"args": ["--init-file", "sys/export.sh"]
},
"Build zsh": {
"path": "zsh",
"icon": "terminal",
"color": "terminal.ansiGreen",
"overrideName": true,
"env": {"ZDOTDIR": "sys/zdotdir"},
"args": []
}
},
"terminal.integrated.defaultProfile.osx": "Build zsh",
"terminal.integrated.profiles.osx": {
"Build bash": {
"path": "bash",
"icon": "terminal-bash",
"color": "terminal.ansiGreen",
"overrideName": true,
"env": {},
"args": ["--init-file", "sys/export.sh"]
},
"Build zsh": {
"path": "zsh",
"icon": "terminal",
"color": "terminal.ansiGreen",
"overrideName": true,
"env": {"ZDOTDIR": "sys/zdotdir"},
"args": []
}
},
// Cortex-Debug
"cortex-debug.armToolchainPath": "${userHome}/.xpack-dev-tools/xpack-arm-none-eabi-gcc-12.3.1-1.2/bin",
// C/C++
"C_Cpp.autoAddFileAssociations": false,
// Task Buttons extention
"VsCodeTaskButtons.showCounter": false,
"VsCodeTaskButtons.tasks": [
{
"label": "$(tools) M2 Release",
"alignment": "left",
"task": "Build M2 Release"
},
{
"label": "$(tools) M3 Release",
"alignment": "left",
"task": "Build M3 Release"
},
{
"label": "$(tools) M2 Debug",
"alignment": "left",
"task": "Build M2 Debug"
},
{
"label": "$(tools) M3 Debug",
"alignment": "left",
"task": "Build M3 Debug"
},
{
"label": "$(tools) Clean",
"alignment": "left",
"task": "Clean"
},
],
"workbench.editorAssociations": {
"*.o": "hexEditor.hexedit",
"*.elf": "hexEditor.hexedit",
"*.bin": "hexEditor.hexedit",
"*.fw": "hexEditor.hexedit"
},
"search.exclude": {
"build/**": true
}
}

125
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,125 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Build M2 Release",
"type": "process",
"command": "bash",
"args": ["-c", ". sys/export.sh && make -e MODEL=M2 release"],
"windows": {
"command": "C:/Windows/System32/cmd.exe",
"args": ["/c call sys/export.bat && make -e MODEL=M2 release"]
},
"osx": {
"type": "shell"
},
"icon": {"id": "tools", "color": "terminal.ansiGreen"},
"options": {
"cwd": "${workspaceRoot}"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "Build M3 Release",
"type": "process",
"command": "bash",
"args": ["-c", ". sys/export.sh && make -e MODEL=M3 release"],
"windows": {
"command": "C:/Windows/System32/cmd.exe",
"args": ["/c call sys/export.bat && make -e MODEL=M3 release"]
},
"osx": {
"type": "shell"
},
"icon": {"id": "tools", "color": "terminal.ansiGreen"},
"options": {
"cwd": "${workspaceRoot}"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "Build M2 Debug",
"type": "process",
"command": "bash",
"args": ["-c", ". sys/export.sh && make -e MODEL=M2 debug"],
"windows": {
"command": "C:/Windows/System32/cmd.exe",
"args": ["/c call sys/export.bat && make -e MODEL=M2 debug"]
},
"osx": {
"type": "shell"
},
"icon": {"id": "tools", "color": "terminal.ansiGreen"},
"options": {
"cwd": "${workspaceRoot}"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "Build M3 Debug",
"type": "process",
"command": "bash",
"args": ["-c", ". sys/export.sh && make -e MODEL=M3 debug"],
"windows": {
"command": "C:/Windows/System32/cmd.exe",
"args": ["/c call sys/export.bat && make -e MODEL=M3 debug"]
},
"osx": {
"type": "shell"
},
"icon": {"id": "tools", "color": "terminal.ansiGreen"},
"options": {
"cwd": "${workspaceRoot}"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
},
{
"label": "Clean",
"type": "process",
"command": "bash",
"args": ["-c", ". sys/export.sh && rm -rf build"],
"windows": {
"command": "C:/Windows/System32/cmd.exe",
"args": ["/c call sys/export.bat && rm -rf build"]
},
"osx": {
"type": "shell"
},
"icon": {"id": "tools", "color": "terminal.ansiGreen"},
"options": {
"cwd": "${workspaceRoot}"
},
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$gcc"
]
}
]
}

237
Makefile Normal file
View File

@@ -0,0 +1,237 @@
# Use install.sh for Build Tools installation
# Use . export.sh for PATH settings
# https://stackoverflow.com/questions/1612278/pre-build-step-in-makefile
TARGET = CAN_FW
DEBUG = 1
OPT = -Og
ifeq ($(DEBUG), 1)
BUILD_DIR = build/$(MODEL)_Debug
else
BUILD_DIR = build/$(MODEL)_Release
endif
#######################################
# SOURCES
#######################################
C_SOURCES = \
CPP_SOURCES = \
$(wildcard libs/*.cpp) \
$(wildcard src/*.cpp) \
$(wildcard src/immo/*.cpp)
ASM_SOURCES = \
#######################################
# INCLUES
#######################################
# AS includes
AS_INCLUDES =
# C includes
C_INCLUDES = \
-Ilibs \
-Isrc
#######################################
# OTHER MAKE VARIABLES
#######################################
CXX = arm-none-eabi-g++
CC = arm-none-eabi-gcc
AS = arm-none-eabi-gcc -x assembler-with-cpp
CP = arm-none-eabi-objcopy
SZ = arm-none-eabi-size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
# mcu
MCU = -mcpu=cortex-m3 -mthumb
# AS defines
AS_DEFS =
# C defines
C_DEFS = -DSTM32F10X_CL -DHSE_VALUE=16000000 -DCAN_FIRMWARE=1
# CXX defines
CXX_DEFS = -DSTM32F10X_CL -DHSE_VALUE=16000000 -DCAN_FIRMWARE=1
ifeq ($(MODEL),M2)
C_DEFS += -DMOBICAR_1_2=1
CXX_DEFS += -DMOBICAR_1_2=1
endif
ifeq ($(MODEL),M3)
C_DEFS += -DMOBICAR_3=1
CXX_DEFS += -DMOBICAR_3=1
endif
# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections
CXXFLAGS = $(MCU) $(CXX_DEFS) $(C_INCLUDES) $(OPT)
CXXFLAGS += -Wall# All warnings
CXXFLAGS += -fmessage-length=0# Number of lines for error messages
CXXFLAGS += -fsigned-char# Default char is signed
CXXFLAGS += -fdata-sections -ffunction-sections# Place each function or data item into its own section (use garbage collector --gc-sections in linker)
CXXFLAGS += -ffreestanding# Freestanding environment (without standard library)
CXXFLAGS += -Wuninitialized# Uninitialized variables warning
CXXFLAGS += -Wpointer-arith# Warning for arithmetic operations with 'void *'
CXXFLAGS += -Wshadow# Warning if a local var shadows another one
CXXFLAGS += -Wlogical-op# Warn about suspicious uses of logical operators in expressions
CXXFLAGS += -Waggregate-return# Warn if any functions that return structures or unions are defined or called
CXXFLAGS += -Wfloat-equal# Warn if floating-point values are used in equality comparisons
CXXFLAGS += -std=gnu++11# C++ standart
CXXFLAGS += -fabi-version=0# Fix ABI version
CXXFLAGS += -fno-exceptions# Disable the generation of code needed to support C++ exceptions
CXXFLAGS += -fno-rtti# Disable C++ runtime
CXXFLAGS += -fno-use-cxa-atexit# Do not use standard library for calling destructors
CXXFLAGS += -fno-threadsafe-statics# Do not emit the extra code to use the routines specified in the C++ ABI for thread-safe initialization of local statics
ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf -ggdb
CXXFLAGS += -g -gdwarf -ggdb
C_DEFS += -DDEBUG
CXX_DEFS += -DDEBUG
endif
# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
CXXFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
#######################################
# LDFLAGS
#######################################
# link script
ifeq ($(MODEL),M2)
LDSCRIPT = sys/M1_CAN_FW.ld
endif
ifeq ($(MODEL),M3)
LDSCRIPT = sys/M3_CAN_FW.ld
endif
LDFLAGS = $(MCU)
LDFLAGS += -Wl,--gc-sections# Dead code removal (linker garbage collector)
LDFLAGS += -Wl,--print-memory-usage# Print FLASH/RAM memory table
LDFLAGS += -T$(LDSCRIPT)# Linker script
# LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map# MAP file
LDFLAGS += -nostartfiles# Do not use startup code before the main()
LDFLAGS += -nodefaultlibs# Do not use default libs
LDFLAGS += -nostdlib# Do not use std lib
LDFLAGS += -Wl,--no-warn-rwx-segment# Remove RWX warning
#######################################
# build the application
#######################################
# list of cpp program objects
OBJECTS = $(addprefix $(BUILD_DIR)/, $(CPP_SOURCES:.cpp=.cpp.o))
# list of C objects
OBJECTS += $(addprefix $(BUILD_DIR)/, $(C_SOURCES:.c=.c.o))
# list of ASM program objects
UPPER_CASE_ASM_SOURCES = $(filter %.S, $(ASM_SOURCES))
LOWER_CASE_ASM_SOURCES = $(filter %.s, $(ASM_SOURCES))
OBJECTS += $(addprefix $(BUILD_DIR)/, $(UPPER_CASE_ASM_SOURCES:.S=.S.o))
OBJECTS += $(addprefix $(BUILD_DIR)/, $(LOWER_CASE_ASM_SOURCES:.s=.s.o))
# default action
.DEFAULT_GOAL := all
all:
@echo Use MODEL variable with debug/release target:
@echo make -e MODEL=M2 debug
@echo make -e MODEL=M2 release
@echo make -e MODEL=M3 debug
@echo make -e MODEL=M3 release
# Colors
NC =\e[0m
RED =\e[0;31m
GREEN =\e[0;32m
BLUE =\e[0;36m
.SECONDEXPANSION:
ERROR_HANDLER = && printf "$(GREEN)OK$(NC)\n" || (printf "$(RED)ERROR$(NC)\n"; exit 1)
$(BUILD_DIR)/%.cpp.o: %.cpp Makefile | $$(@D)/
@printf "compile $(BLUE)$<$(NC) "
@$(CXX) -E -c $(CXXFLAGS) $< -o $@ || (printf "$(RED)ERROR$(NC)\n"; exit 1)
@iconv -f UTF-8 -t CP1251 $@ > $@.i
@$(CXX) -c $(CXXFLAGS) $@.i -o $@ $(ERROR_HANDLER)
$(BUILD_DIR)/%.c.o: %.c Makefile | $$(@D)/
@printf "compile $(BLUE)$<$(NC) "
@$(CC) -c $(CFLAGS) $< -o $@ $(ERROR_HANDLER)
$(BUILD_DIR)/%.s.o: %.s Makefile | $$(@D)/
@printf "compile $(BLUE)$<$(NC) "
@$(AS) -c $(CFLAGS) $< -o $@ $(ERROR_HANDLER)
$(BUILD_DIR)/%.S.o: %.S Makefile | $$(@D)/
@printf "compile $(BLUE)$<$(NC) "
@$(AS) -c $(CFLAGS) $< -o $@ $(ERROR_HANDLER)
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
@printf "linking $(BLUE)$@$(NC)\n"
@$(CXX) $(OBJECTS) $(LDFLAGS) -o $@ || (printf "$(RED)linker ERROR$(NC)\n"; exit 1)
# $(SZ) $@
# https://www.cmcrossroads.com/article/making-directories-gnu-make
%/:
@mkdir -p $@
$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf
@printf "generate $(BLUE)$@$(NC) "
@$(HEX) $< $@ $(ERROR_HANDLER)
@sys/hex2fw.sh $@ || exit 1
ifeq ($(DEBUG), 1)
STARTMSG = Building $(MODEL) Debug
else
STARTMSG = Building $(MODEL) Release
endif
build_app:
@printf "$(GREEN)-----------------------$(NC)\n"
@printf "$(GREEN) $(STARTMSG)$(NC)\n"
@printf "$(GREEN)-----------------------$(NC)\n"
@sys/version.sh;
# @sys/changelog.sh;
@make -j --no-print-directory --output-sync $(BUILD_DIR)/$(TARGET).hex
@printf "$(GREEN)-----------------------$(NC)\n"
clean:
@rm -rf $(BUILD_DIR)
debug:
@make clean --no-print-directory
@make build_app --no-print-directory
release:
@make clean --no-print-directory -e DEBUG=0
@make build_app --no-print-directory -e OPT=-Os DEBUG=0
printvars:
@echo "MODEL: $(MODEL)"
@echo "C_DEFS: $(C_DEFS)"
@echo "CXX_DEFS: $(CXX_DEFS)"
-include $(OBJECTS:.o=.d)
# *** EOF ***

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
## Шаблон проекта CAN-прошивки
[Подготовка к работе](sys/info/install.md)

73
libs/Buffer.h Normal file
View File

@@ -0,0 +1,73 @@
/*
* Buffer.h
*
* Created on: 03 апр. 2015 г.
* Author: esaulenko
*/
#ifndef _BUFFER_H_
#define _BUFFER_H_
#include <cstdint>
// простейший кольцевой буфер.
// проверки при добавлении/извлечении данных отсутствуют, надо проверять отдельно!!
template <typename Type = char, int Size = 32>
class CircularBuffer
{
private:
Type buff[Size];
volatile uint32_t putIdx;
volatile uint32_t getIdx;
public:
CircularBuffer()
{
Flush ();
}
void Put (const Type & data)
{
buff[putIdx] = data;
putIdx = (putIdx + 1) % Size;
}
Type Get ()
{
Type data = buff[getIdx];
getIdx = (getIdx + 1) % Size;
return data;
}
Type & View ()
{
return buff[getIdx];
}
uint32_t Avail () const
{
int32_t avail = putIdx - getIdx;
if (avail < 0) avail += Size;
return avail;
}
uint32_t Free () const
{
int32_t free = getIdx - putIdx - 1;
if (free < 0) free += Size;
return free;
}
void Flush ()
{
putIdx = getIdx = 0;
}
};
#endif /* _BUFFER_H_ */

288
libs/Can.h Normal file
View File

@@ -0,0 +1,288 @@
/*
* Can.h
*
* Created on: 01 июня 2015 г.
* Author: esaulenko
*/
#ifndef DRIVERS_CAN_CAN_H_
#define DRIVERS_CAN_CAN_H_
#include <stdint.h>
#include "CommonTypes.h"
#ifndef CAN_FIRMWARE
#include "SysTimer.h"
#include "Buffer.h"
#include "scmRTOS.h"
#endif
struct TCanPkt
{
uint32_t id;
uint8_t data[8];
uint8_t data_len;
TCanPkt() { }
TCanPkt (uint32_t pkt_id):
id(pkt_id) { }
// принимает строку, заполняет данные пакета. Неуказанные данные заполняются нулями
template <int N>
inline void SetData (const char (&data_str)[N])
{
int data_size = (N <= 8) ? (N - 1) : 8;
for (int i = 0; i < data_size; i++)
data[i] = data_str[i];
for (int i = data_size; i < 8; i++)
data[i] = 0x00;
}
inline void SetData (uint8_t A)
{ data_len = 1;
data[0] = A; data[1] = 0; data[2] = 0; data[3] = 0;
data[4] = 0; data[5] = 0; data[6] = 0; data[7] = 0;
}
inline void SetData (uint8_t A, uint8_t B)
{ data_len = 2;
data[0] = A; data[1] = B; data[2] = 0; data[3] = 0;
data[4] = 0; data[5] = 0; data[6] = 0; data[7] = 0;
}
inline void SetData (uint8_t A, uint8_t B, uint8_t C)
{ data_len = 3;
data[0] = A; data[1] = B; data[2] = C; data[3] = 0;
data[4] = 0; data[5] = 0; data[6] = 0; data[7] = 0;
}
inline void SetData (uint8_t A, uint8_t B, uint8_t C, uint8_t D)
{ data_len = 4;
data[0] = A; data[1] = B; data[2] = C; data[3] = D;
data[4] = 0; data[5] = 0; data[6] = 0; data[7] = 0;
}
inline void SetData (uint8_t A, uint8_t B, uint8_t C, uint8_t D, uint8_t E)
{ data_len = 5;
data[0] = A; data[1] = B; data[2] = C; data[3] = D;
data[4] = E; data[5] = 0; data[6] = 0; data[7] = 0;
}
inline void SetData (uint8_t A, uint8_t B, uint8_t C, uint8_t D, uint8_t E, uint8_t F)
{ data_len = 6;
data[0] = A; data[1] = B; data[2] = C; data[3] = D;
data[4] = E; data[5] = F; data[6] = 0; data[7] = 0;
}
inline void SetData (uint8_t A, uint8_t B, uint8_t C, uint8_t D, uint8_t E, uint8_t F, uint8_t G)
{ data_len = 7;
data[0] = A; data[1] = B; data[2] = C; data[3] = D;
data[4] = E; data[5] = F; data[6] = G; data[7] = 0;
}
inline void SetData (uint8_t A, uint8_t B, uint8_t C, uint8_t D, uint8_t E, uint8_t F, uint8_t G, uint8_t H)
{ data_len = 8;
data[0] = A; data[1] = B; data[2] = C; data[3] = D;
data[4] = E; data[5] = F; data[6] = G; data[7] = H;
}
};
struct TCanInit
{
uint32_t baudrate; // "сырое" значение регистра BTR, см. TCanBaudrate
uint8_t mode; // в наст. момент не используется. TODO Должно быть RO / RW
uint64_t filters[27]; // массив со значениями для пар регистров; заполняется Filters::xxx
};
class CCan
{
public:
enum TCanState : uint8_t
{
CanActive,
CanRxOnly, // внешний драйвер выключен
CanSleep, // внешний драйвер выключен, модуль в спящем режиме
CanInitError = 0xFE,
CanBusOff = 0xFF,
};
/* TIME QUANTUM FREQUENCY:
Ftq = Ntq * Fbaud
where 8 <= Ntq <= 25, and Ntq - is integer!
BAUD RATE PRESCALER:
BRP = (Fcan/Ftq)–1
INDIVIDUAL BIT TIME SEGMENTS:
(Bit Time) = (Sync Segment) + (Time Segment 1) + (Time Segment 2)
where
(Sync Segment) = 1*Tq (constant)
(Time Segment 2) ~= 30% of Nominal Bit Time = Ntq/3
(Time Segment 2) > 1*Tq
(Time Segment 1) > 3*Tq
(Time Segment 1) > (Time Segment 2)
(Time Segment 1) <= (Time Segment 2)+8
(Synchronous Jump Width) <= (Time Segment 2)
Table of Parameters:
--------+-----------------------------------------------------+
BRP@Fcan| Ntq |
9MHz |25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10| 9| 8|
--------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
500.000 | | | | | | | | 0| | | | | | | | | 1| |
250.000 | | | | | | | | 1| | | | | | 2| | | 3| |
125.000 | | 2| | | | | | 3| | | | | | 5| | | 7| 8|
100.000 | | | | | | | | 4| | | 5| | | | | 8| 9| |
83.333 | | | | | | | | 5| | | | | | 8| | |11| |
50.000 | | | | | | 8| | 9| | |11| | |14| |17|19| |
33.333 | | | | | | | |14| | |17| | | | |26|29| |
20.000 |17| | | | | | |24| | |29| | | | |44|49| |
15.000 |23|24| | | |29| | | | |39| | |49| |59| |74|
10.000 |35| | | | |44| |49| | |59| | |74| |89|99| |
--------+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
*/
#define CAN_BTR(BRP,TSEG1,TSEG2,SJW) (((((((SJW)&0x03)<<4)|((TSEG2)&0x07))<<4)|((TSEG1)&0x0F))<<16)|((BRP)&0x3FF)
// значения регистра BTR
enum TCanBaudrate {
CanBaudrate500 = CAN_BTR(0,10,5,3),
CanBaudrate250 = CAN_BTR(1,10,5,3),
// CanBaudrate125 = CAN_BTR(2,14,7,3),
CanBaudrate125 = CAN_BTR(3,10,5,3),
CanBaudrate100 = CAN_BTR(4,10,5,3),
CanBaudrate83 = CAN_BTR(5,10,5,3),
// CanBaudrate50 = CAN_BTR(8,11,6,3),
CanBaudrate50 = CAN_BTR(9,10,5,3),
CanBaudrate33 = CAN_BTR(14,10,5,3),
CanBaudrate20 = CAN_BTR(17,15,7,3),
// CanBaudrate20 = CAN_BTR(24,10,5,3),
CanBaudrate15 = CAN_BTR(23,15,7,3),
// CanBaudrate15 = CAN_BTR(24,14,7,3),
// CanBaudrate15 = CAN_BTR(29,11,6,3),
CanBaudrate10 = CAN_BTR(35,15,7,3),
// CanBaudrate10 = CAN_BTR(44,11,6,3),
// CanBaudrate10 = CAN_BTR(49,10,5,3),
};
#ifndef CAN_FIRMWARE
CCan ();
uint32_t Init (TCanChannel aCh, const TCanInit * apInit);
uint32_t Send (TCanChannel aCh, TCanPkt * apPkt, uint32_t aTimeout);
void ReceivedIsr (TCanChannel aCh, TCanPkt * apPkt);
uint32_t ProcessQueue ();
uint32_t GetRcv (TCanChannel aCh, TCanPkt * apPkt);
uint32_t GetRcvTimeout (TCanChannel aCh)
{ return _rx_tmr[aCh].Value(); }
#endif // CAN_FIRMWARE
// объявление фильтров при инициализации
struct Filter {
// добавить пару идентификаторов для точного соответствия
static constexpr uint64_t List11 (uint16_t id1, uint16_t id2)
{
return ((uint64_t) (IdStd (id1) | 0x01) << 32) |
(uint64_t) (IdStd (id2) | 0x01);
}
static constexpr uint64_t List29 (uint32_t id1, uint32_t id2)
{
return ((uint64_t) (IdExt (id1) | 0x01) << 32) |
(uint64_t) (IdExt (id2) | 0x01);
}
// добавить один идентификатор
static constexpr uint64_t List11 (uint16_t id1)
{
return ((uint64_t) (IdStd (id1) | 0x01) << 32) |
(uint64_t) (IdStd (id1) | 0x01);
}
static constexpr uint64_t List29 (uint32_t id1)
{
return ((uint64_t) (IdExt (id1) | 0x01) << 32) |
(uint64_t) (IdExt (id1) | 0x01);
}
// добавить один идентификатор с маской
static constexpr uint64_t Mask11 (uint16_t id, uint16_t mask)
{
return ((uint64_t) (IdStd (id)) << 32) |
(uint64_t) (IdStd (mask) | 0x01);
}
static constexpr uint64_t Mask29 (uint32_t id, uint32_t mask)
{
return ((uint64_t) (IdExt (id)) << 32) |
(uint64_t) (IdExt (mask) | 0x01);
}
private:
// формирование ID для фильтров
static constexpr uint32_t IdStd (uint16_t id)
{ return (id & 0x7FFul) << 21; }
static constexpr uint32_t IdExt (uint32_t id)
{ return ((id & 0x1FFFFFFFul) << 3) | 0x04; }
};
#ifndef CAN_FIRMWARE
private:
uint8_t sleep_en;
bool IsSleepEn (TCanChannel aCh)
{ return sleep_en & aCh; }
// очередь пакетов на отправку - тот же TCanPkt, но с таймером
struct TCanPktTxInt: public TCanPkt {
uint32_t timeout;
TimerMs tmr;
};
typedef CircularBuffer<TCanPkt, 16> TRxBuf;
typedef CircularBuffer<TCanPktTxInt, 32> TTxBuf;
TRxBuf _rx_buf[2];
TTxBuf _tx_buf[2];
uint32_t TxByTimeout (TCanChannel aCh);
bool IsTxQueueEmpty (TCanChannel aCh);
TCanState _state[2];
// Send() и обработка очереди вызываются из разных потоков, нужна защита
OS::TMutex can_mutex;
// сбрасывается по приёму любого пакета
TimerMs _rx_tmr[2];
#endif // CAN_FIRMWARE
};
extern CCan gCan;
#endif /* DRIVERS_CAN_CAN_H_ */

99
libs/CanFwInterface.cpp Normal file
View File

@@ -0,0 +1,99 @@
/*
* CanFwInterface.cpp
*
* Created on: 13 мая 2015 г.
* Author: esaulenko
*/
#include "ModelName.h"
#include "source/SourcePath.h"
#include SRC_HEADER
#include "CanFwInterface.h"
#include "Utils.h"
#include "Settings.h"
#include "Version.h"
#include <stddef.h>
// заглушка для неиспользуемых функций
//void Empty (__attribute__((unused)) void * apCanFwMem) {};
void Empty () {};
// контрольная сумма, располагается линкером в самом конце прошивки
__attribute__ ((section(".CheckSum")))
static const uint32_t CanChksum = CHKSUM_DEBUG;
// описание прошивки
const TCanFwInfo gCanFwInfo =
{
(CAN_FW_VERSION << 24) | BUILD_DATE, // Version - Версия ПО
GIT_BUILD, // Хеш коммита в репозитории git
&CanChksum, // *pCRC32 - Адрес, где расположена CRC32
0, // reserved2
M_NAME CAN_FW_DESCRIPTION "_" GIT_VERSION // TextInfo[64] - Текстовая информация
};
// структура с функциями CAN, которые вызываются из ядра
__attribute__ ((section(".entrance_vector")))
TCanFunctions CanFuctTable =
{
&gCanFwInfo, // pCanFwInfo
(uint8_t *) & CSettings::CanSettingsTable, // pSettingsTable
CSettings::CanSettingsName, // pSettingsNames
Init,
PeriodicProcess,
SettingChanged,
Empty, // Reserved6
InputChanged,
OutputChanged,
GuardEvent,
Can1Received,
Can2Received,
SequenceStart,
SequenceStop,
Command,
Lin1Received,
Lin2Received,
Lin1Transmitted,
Lin2Transmitted,
#if defined MOBICAR_1_2
Empty, // Reserved19
Empty, // Reserved20
#elif defined MOBICAR_3
Lin3Received,
Lin3Transmitted,
#endif
Empty, // Reserved21
Empty, // Reserved22
Empty, // Reserved23
Empty, // Reserved24
Empty, // Reserved25
Empty, // Reserved26
Empty, // Reserved27
Empty, // Reserved28
Empty, // Reserved29
Empty, // Reserved30
Empty, // Reserved31
};
// проверка, что переменные влезают в соотв.область
static_assert (sizeof(TCanFwMem) <= gCanFwMemSize, "Превышен максимальный размер TCanFwMem");

291
libs/CanFwInterface.h Normal file
View File

@@ -0,0 +1,291 @@
/*
* CanFwInterface.h
*
* Created on: 13 мая 2015 г.
* Author: esaulenko
*/
#ifndef CANFWINTERFACE_H_
#define CANFWINTERFACE_H_
#include "CommonTypes.h"
// размер области памяти под переменные CAN-прошивки
enum { gCanFwMemSize = 2048 };
// объявляем структуры заранее, чтобы не было взаимных ссылок
struct TCanPkt;
union TLinInit;
struct TLinFrame;
#if CAN_FIRMWARE
struct TCanFwMem;
#else // Core
typedef char TCanFwMem[gCanFwMemSize];
#endif
// команды ядра, которые может вызывать CAN-прошивка
enum TCoreCommands : uint8_t {
CoreCmdDisarm = 1, // команда снятия с охраны Параметр: b00CHASFL
// бит 0(L) - отпирать замки;
// бит 1(F) - мигать поворотниками;
// бит 2(S) - гудеть сиреной;
// бит 3(A) - если команда подана в режиме тревоги, прекратить ее, не снимая с охраны;
// бит 4(H) - режим Handsfree, позволяет сниматься с Охраны в любой момент начала Автозапуска и блокирует Перепостановку;
// бит 5(C) - выдавать сигналы управления функциями Комфорта.
CoreCmdArm = 2, // команда постановки на охрану Параметр: b00C00SFL
// бит 0(L) - запирать замки;
// бит 1(F) - мигать поворотниками;
// бит 2(S) - гудеть сиреной;
// бит 5(C) - выдавать сигналы управления функциями Комфорта.
CoreCmdTrunkOpened = 3, // команда оповещения Системы о том, что багажник открыт: b00000SF0
//CoreCmdAlarm = 6, // не реализовано
CoreCmdDisableShockSens = 7, // Отключить реакцию на датчик Удара в течении <Параметр> времени в мсек
CoreCmdDisableDoorSens = 8, // Задержать реакцию на концевики дверей в течении <Параметр> времени в мсек
CoreCmdLauncherOn = 9, // команда оповещения Системы о включении внешнего запуска: <Параметр> - время ожидания запуска в сек
CoreCmdLauncherOff = 10, // команда оповещения Системы о выключении внешнего запуска: <Параметр> - время ожидания глушения или перезапуска в сек
CoreCmdDisableTrunkSens = 11, // Задержать реакцию на концевики багажника в течении <Параметр> времени в мсек
CoreCmdImmoLearnRes = 12, // Результат обучения иммобилайзера: 0 - успех, нужно запомнить VIN, 0x80 - успех, VIN не нужен, другое - ошибка
CoreCmdImmoLearnContinue = 13, // Управление обучением иммо: 1 - перезапуск таймаута; 2 - необходимо выключить зажигание; 3 - подать сигнал антенным модулем
CoreCmdStartStop = 14, // Управление запуском со штатного брелока (например, трехкратным нажатием на кнопку закрыть)
CoreCmdMenuResult = 15, // Результат выполнения команды из меню антенны: 0 - успех, 1 - ошибка
};
// Список команд предназначеных/определенных/известных CAN прошивке
enum TCanFwCommands : uint8_t {
ccNone = 0, // нет команды/не команда, либо команда неизвестна/неопределена...
ccLockDoors = 1, // Запереть все двери
ccUnLockDoors = 2, // Отпереть все двери
ccUnLockDoorDrv = 3, // Отпереть дверь водителя
ccLockTrunk = 4, // Запереть багажник
ccUnLockTrunk = 5, // Отпереть багажник
ccLockHood = 6, // Запереть капот
ccUnLockHood = 7, // Отпереть капот
ccCloseWindows = 8, // Закрыть окна
ccOpenWindows = 9, // Открыть окна
ccService = 10, // включение режима Автосервис
ccDisarm = 11, // выключение режима Охраны
//reserved = 12,
ccArm = 13, // включение режима Охраны
//reserved = 14,
//reserved = 15,
ccAlarmOff = 16, // выключить Тревогу
ccAlarmOn = 17, // включить Тревогу
ccPanicOff = 18, // выключение режима Паника
ccPanicOn = 19, // включение режима Паника
ccImmobilizerOff = 20, // выключить Иммобилайзер
ccImmobilizerOn = 21, // включить Иммобилайзер
ccIgnSupportOff = 22, // выключение поддержки зажигания
ccIgnSupportOn = 23, // включение поддержки зажигания
ccBlockageOff = 24, // выключить блокировку
ccBlockageOn = 25, // включить блокировку
ccEngineStart = 26, // запуск двигателя (по ошибке, стало событием)
ccEngineStop = 27, // глушение двигателя (по ошибке, стало событием)
ccTestMode = 28, // включение Тест-режима
ccFoldMirrors = 29, // сложить зеркала
ccUnFoldMirrors = 30, // разложить зеркала
ccCloseSunroof = 31, // закрыть люк
ccHeatedSeatsOn = 32, // включить подогрев сидений
ccHeatedSeatsOff = 33, // выключить подогрев сидений
ccPreHeaterOff = 34, // выключить предпусковой подогреватель
ccPreHeaterOn = 35, // включить предпусковой подогреватель
ccAutoStartOff = 36, // выключение запуска
ccAutoStartOn = 37, // включение запуска
ccAutoStartDone = 38, // успешный запуск
ccKillEngine = 39, // заглушить двигатель!
ccImmoBypass = 40, // обходчик иммобилайзера: бит 0 - включить; бит 1 - режим обучения
ccUpdateVin = 41, // обновить VIN-код
ccSendObdReq = 42, // запрос OBD-диагностики
ccValetMenuCmd = 43, // команда из меню антенны
ccHeatedWindowsOn = 44, // включить подогрев окон
ccHeatedWindowsOff = 45, // выключить подогрев окон
};
// Параметры команд для CAN прошивки, битовая маска (всего 24 бита)
enum TCanFwCommandParam : uint32_t {
mccReserved = (1 << 0), // резерв
mccSilent = (1 << 1), // беззвучное исполнение команды
mccPriority = (1 << 2), // приоритетное открытие двери водителя (ccDisarm)
mccDriveBuiltinSystem = (1 << 3), // разрешено управлять штатной охранной системой (ccLockTrunk/ccUnLockTrunk)
};
// данные, которые CAN-прошивка может передать в ядро
enum TCanFwData : uint8_t {
CanData_RPM = 0, // обороты, об/мин
CanData_Speed = 1, // скорость, км/ч
CanData_Odometer = 2, // пробег, 1 ед = 100 метров
CanData_Accelerator = 3, // положение педали газа, проценты
CanData_BrakeForce = 4, // положение педали тормоза, проценты
CanData_WheelAngle = 5, // положение руля
CanData_FuelLevel = 6, // уровень топлива, проценты
CanData_FuelConsumption = 7, // мгновенный расход, миллилитры
CanData_CoolantTemp = 8, // температура двигателя, со смещением 40 градусов
CanData_VIN = 9, // VIN-код
CanData_FuelLevelRaw = 10, // уровень топлива, без калибровки 0..255
CanData_COUNT, // количество возможных полей с данными
CanData_Invalid = 0x80,
};
// описание CAN-прошивки
extern const TCanFwInfo gCanFwInfo;
// структура с функциями CAN, которые вызываются из ядра
struct TCanFunctions
{
TCanFwInfo const * pCanFwInfo;
uint8_t const * pSettingsTable;
char const * const * pSettingsNames;
void (*Init)(TCanFwMem * vars);
void (*Periodic)(TCanFwMem * vars);
void (*SettingChanged)(TCanFwMem * vars, uint16_t id);
void (*Reserved6)();
void (*InputChanged)(TCanFwMem * vars, uint32_t aInput, bool aSwitchedOn);
void (*OutputChanged)(TCanFwMem * vars, uint32_t aOutput, bool aSwitchedOn);
void (*GuardEvent)(TCanFwMem * vars, TGuardEvents aEvent);
void (*Can1Received)(TCanFwMem * vars, TCanPkt *apPkt);
void (*Can2Received)(TCanFwMem * vars, TCanPkt *apPkt);
void (*SequenceStart)(TCanFwMem * vars, uint32_t aOutputNum);
void (*SequenceStop)(TCanFwMem * vars, uint32_t aOutputNum);
void (*Command)(TCanFwMem * vars, TCanFwCommands aCmd, uint32_t aCmdParam);
void (*Lin1Received)(TCanFwMem* vars, TLinFrame* apFrame);
void (*Lin2Received)(TCanFwMem* vars, TLinFrame* apFrame);
void (*Lin1Transmitted)(TCanFwMem* vars, uint8_t aFrameId);
void (*Lin2Transmitted)(TCanFwMem* vars, uint8_t aFrameId);
#if defined MOBICAR_1_2
void (*Reserved19)();
void (*Reserved20)();
#elif defined MOBICAR_3 || defined MAGICAR_X
void (*Lin3Received)(TCanFwMem * vars, TLinFrame *apFrame);
void (*Lin3Transmitted)(TCanFwMem * vars, uint8_t aFrameId);
#endif
void (*Reserved21)();
void (*Reserved22)();
void (*Reserved23)();
void (*Reserved24)();
void (*Reserved25)();
void (*Reserved26)();
void (*Reserved27)();
void (*Reserved28)();
void (*Reserved29)();
void (*Reserved30)();
void (*Reserved31)();
};
static_assert (sizeof(TCanFunctions) == 4*32, "В таблице должно быть 32 поля");
// структура с функциями ядра, которые вызываются из CAN-прошивки
struct TCoreFunctions
{
const TCoreInfo* pCoreInfo;
uint32_t (*GetTickMs) ();
uint32_t (*CanInit) (TCanChannel aCh, const TCanInit* apInit);
uint32_t (*CanSend) (TCanChannel aCh, TCanPkt* apPkt, uint32_t timeout);
uint64_t (*GetInputs) ();
uint64_t (*GetOutputs) ();
#if defined MOBICAR_3 && 1 // Только для отладки (работает только с отладочной или спец. прошивками)
typedef struct {
uint8_t BlinkOff; // [50ms]
uint8_t BlinkOn; // [50ms]
uint8_t BeepTime; // [50ms]
uint8_t BeepTone;
} TDebugIndicate;
void (*DebugIndicate)(TDebugIndicate const & aIndicate, const uint8_t nBlink);
#else
void (*Reserved6)();
#endif
uint32_t (*Command) (TCoreCommands aCmd, uint32_t aParam);
uint32_t (*RunSequence) (uint32_t aOutput, uint32_t aSequenceNum);
uint32_t (*SetPeriod) (uint32_t aPeriod);
uint32_t (*SetOutput) (uint32_t aOutput, bool On);
uint32_t (*InputState) (uint32_t aInput, bool On);
uint32_t (*DataValue) (uint32_t aDataIdx, int32_t aValue);
uint32_t (*CanGetRxTimeout) (TCanChannel aCh);
uint32_t (*LinInit) (TLinChannel aCh, const TLinInit* apInit);
uint32_t (*LinSend) (TLinChannel aCh, const TLinFrame* apFrame);
uint32_t (*LinSleep) (TLinChannel aCh, bool aSleep);
void (*Reserved17)();
uint32_t (*DataValueArr) (uint32_t aDataIdx, const void * data);
bool (*CheckVinValid) ();
bool (*SaveSetting) (uint16_t id, const void * apData, uint16_t aDataSize);
const void *(*GetSetting) (uint16_t id);
bool (*SaveImmoLearn) (const void *data, uint32_t dataSize);
void (*Reserved23)();
void (*Reserved24)();
void (*Reserved25)();
void (*Reserved26)();
void (*Reserved27)();
void (*Reserved28)();
void (*Reserved29)();
void (*Reserved30)();
void (*DebugConsole)(const char *, ...);
};
static_assert (sizeof(TCoreFunctions) == 4*32, "В таблице должно быть 32 поля");
// таблица с доступными функциями ядра
#define CoreFunc ((TCoreFunctions*) ((uint32_t) &FW_AREAS->Core + 512) ) // 16K + 512
#if defined CAN_FIRMWARE
// объявление функций CAN-прошивки
void Init (TCanFwMem * vars);
void SettingChanged (TCanFwMem * vars, uint16_t id);
void Can1Received (TCanFwMem * vars, TCanPkt *apPkt);
void Can2Received (TCanFwMem * vars, TCanPkt *apPkt);
void InputChanged (TCanFwMem * vars, uint32_t aInputNum, bool aSwitchedOn);
void OutputChanged (TCanFwMem * vars, uint32_t aOutputNum, bool aSwitchedOn);
void GuardEvent (TCanFwMem * vars, TGuardEvents aEvent);
void SequenceStart (TCanFwMem * vars, uint32_t aEvent);
void SequenceStop (TCanFwMem * vars, uint32_t aEvent);
void Command (TCanFwMem * vars, TCanFwCommands aCmd, uint32_t aCmdParam);
void PeriodicProcess (TCanFwMem * vars);
void Lin1Received (TCanFwMem * vars, TLinFrame *apFrame);
void Lin2Received (TCanFwMem * vars, TLinFrame *apFrame);
void Lin3Received (TCanFwMem * vars, TLinFrame *apFrame);
void Lin1Transmitted (TCanFwMem * vars, uint8_t aFrameId);
void Lin2Transmitted (TCanFwMem * vars, uint8_t aFrameId);
void Lin3Transmitted (TCanFwMem * vars, uint8_t aFrameId);
#else // core
// таблица с доступными функциями CAN-прошивки, лежит в её начале
#define CanFwFunc ((TCanFunctions*) &FW_AREAS->CanFw)
#endif
#endif /* CANFWINTERFACE_H_ */

56
libs/CanSources.cpp Normal file
View File

@@ -0,0 +1,56 @@
/*
* CanSources.cpp
*
* Created on: 01 дек. 2015 г.
* Author: esaulenko
*/
#include "source/SourcePath.h"
#ifdef SRC_HEADER
#include SRC_HEADER
#endif
#ifdef SRC_FILE1
#include SRC_FILE1
#endif
#ifdef SRC_FILE2
#include SRC_FILE2
#endif
#ifdef SRC_FILE3
#include SRC_FILE3
#endif
#ifdef SRC_FILE4
#include SRC_FILE4
#endif
#ifdef SRC_FILE5
#include SRC_FILE5
#endif
#ifdef SRC_FILE6
#include SRC_FILE6
#endif
#ifdef SRC_FILE7
#include SRC_FILE7
#endif
#ifdef SRC_FILE8
#include SRC_FILE8
#endif
#ifdef SRC_FILE9
#include SRC_FILE9
#endif
#ifdef SRC_FILE10
#include SRC_FILE10
#endif

335
libs/CommonTypes.h Normal file
View File

@@ -0,0 +1,335 @@
/*
* CommonTypes.h
*
* Created on: 16 апр. 2015 г.
* Author: esaulenko
*/
#ifndef COMMON_COMMONTYPES_H_
#define COMMON_COMMONTYPES_H_
#include <cstdint>
#define member_size(type, member) sizeof(((type*)nullptr)->member)
//typedef uint8_t byte;
//typedef uint16_t word;
typedef unsigned int uint;
typedef unsigned long ulong;
//#define bbRAM(Var,Bit) ((uint*)(((uint)&Var + 0x22000000/32)*32))[Bit]
#define bbRAM(Var,Bit) ((volatile uint*)(((uint)&Var + SRAM_BB_BASE/32)*32))[Bit]
// !!! Начиная с компилятора версии 7, что-то в оптимизаторе изменилось.. и теперь, без volatile
// программа компилируется неверно. Поэтому добавляем признак volatile !!!
#define KByte *1024
union TSysStateRecord
{
uint16_t Record;
struct {
uint8_t Value; // Значение состояния Системы
uint8_t Check; // Проверка данных
} __attribute__((packed));
} __attribute__((packed));
typedef TSysStateRecord TSysState[2 KByte / sizeof(TSysStateRecord)];
struct TFwRegions
{
#if defined MOBICAR_1_2
// страницы по 2 кбайта
const uint8_t Boot[16 KByte];
const uint8_t Core[96 KByte];
const uint8_t CanFw[16 KByte];
const uint8_t Upload[96 KByte];
const uint8_t Settings1[4 KByte];
const uint8_t Settings2[4 KByte];
const uint8_t Reserved[20 KByte];
const uint8_t ImmoLearn[2 KByte];
const TSysState SysState;
#elif defined MOBICAR_3
const uint8_t Boot[16 KByte]; // sector 0
const uint8_t Settings1[16 KByte]; // sector 1
const uint8_t Settings2[16 KByte]; // sector 2
const uint8_t CanFw[16 KByte]; // sector 3
struct {
const uint8_t UploadAux[64 KByte - sizeof(TSysState)]; // sector 4
const TSysState SysState;
} __attribute__((packed));
union {
const uint8_t Upload[128 KByte]; // sector 5
const uint8_t ImmoLearn[2 KByte];
} __attribute__((packed));
const uint8_t Core[2 * 128 KByte]; // sector 6, 7
#endif
};
#define FW_AREAS ((TFwRegions const *)0x08000000)
// специальное значение для контрольной суммы - используется только в отладочной прошивке
#define CHKSUM_DEBUG 0xDebac0ab
// битовая настройка, используется в модуле настроек. Для простоты реализации занимает в ОЗУ 1 байт.
typedef uint8_t bit_t;
// **********
// * Версия *
// **********
union TVersion
{
uint32_t Value;
struct {
uint8_t Day;
uint8_t Month;
uint8_t Year;
uint8_t Version;
} __attribute__((packed));
} __attribute__((packed));
struct TBootInfo {
TVersion Version; // Версия загрузчика
uint16_t Build; // Номер билда загрузчика
uint8_t HwVer; // Версия железа
uint8_t Model; // Модель устройства. Mobicar1 = 0 (!), Mobicar2 = 2
uint32_t SerialNumber; // Серийный номер устройства
uint32_t reserved2;
uint8_t FirmwareKey[32]; // Ключ дешифрования прошивки
uint8_t ServerRegKey[12]; // ключ регистрации на сервере
uint8_t ServerExchKey[16]; // ключ установки соединения с сервером
uint32_t BluetoothPairingCode; // статический код для подшивания BLE устройств
uint32_t reserved[120];
} __attribute__((packed, aligned(4)));
#define TBootInfoSize __builtin_offsetof (TBootInfo, FirmwareKey)
static_assert (TBootInfoSize == 16, "TBootInfo changed!");
struct TCoreInfo {
TVersion Version; // Версия ПО
uint16_t Build; // Номер билда ядра
uint16_t reserved1;
uint32_t const * pCRC32; // Адрес, где расположена CRC32 в прошивке Ядра
uint32_t reserved2;
char TextInfo[64]; // Текстовая информация о прошивке Ядра
} __attribute__((packed, aligned(4)));
static_assert (sizeof(TCoreInfo) == 80, "TCoreInfo changed!");
// Структура массива информации о CAN-прошивке
struct TCanFwInfo {
TVersion Version; // Версия ПО
uint32_t Build; // Хеш коммита в репозитории git
uint32_t const * pCRC32; // Адрес, где расположена CRC32
uint32_t reserved2;
uint8_t TextInfo[64]; // Текстовая информация
} __attribute__((packed, aligned(4)));
static_assert (sizeof(TCanFwInfo) == 80, "TCanFwInfo changed!");
// ********************
// * НАСТРОЙКА ВХОДОВ *
// ********************
struct TInputPinSettings {
uint16_t T1:14; // период активного импульса
uint16_t P1:2; // Подтяжка: [xy]: непрограммируемая(x=0)/программируемая(x=1)/pulldown(y=0)/pullup(y=1).
uint16_t T2:14; // период пассивного импульса
uint16_t P2:2; // Подтяжка: [xy]: непрограммируемая(x=0)/программируемая(x=1)/pulldown(y=0)/pullup(y=1).
// Таблица истинности:
// T1 P1 T2 P2 Debounce
// 0 p 0 x tick статика, без антидребезга
// >0 p 0 x T1 статика с периодом антидребезга равного T1
// 0 p >0 p tick динамика, P1 включается на TICK, затем P2 включается на T2, без антидребезга.
// >0 p >0 p T1 динамика, P1 включается на T1*2, затем P2 включается на T2, антидребезг T1.
} __attribute__((packed));
struct TInputSettings {
uint8_t Input:7; // номер физического входа
uint8_t Invert:1; // Инвертировать состояние
bool operator== (const TInputSettings &other)
{ return *((uint8_t*)this) == *((uint8_t*)(&other)); }
bool operator!= (const TInputSettings &other)
{ return ! (*this == other); }
} __attribute__((packed));
enum {
SequenceLength = 16,
maxSequences = 32, // кол-во импульсных последовательностей одновременно запущенных
};
// последовательности управления выходами
union TSequence {
uint8_t Byte[SequenceLength];
union {
uint8_t Value;
struct {
uint8_t Mantissa:5;
uint8_t Power:3;
};
} Step;
} __attribute__((packed));
typedef uint8_t TKeyAES[16]; // ключ шифрования радио
typedef uint8_t TVehicleID[17]; // VIN-код
//typedef uint8_t TImmoKey[124]; // ключ обходчика иммобилайзера
typedef uint8_t TImmoKey[32]; // ключ обходчика иммобилайзера
// настройка таймера запуска
struct TStartTimerSetting {
uint16_t Time; // количество минут с начала суток. У выключенного таймера биты инвертированы
uint8_t DayMask; // Биты дней недели, когда разрешён запуск - 0..6. Для "старого" механизма устанавливается 0xFF
} __attribute__((packed));
// CAN data forward declarations
struct TCanInit;
struct TCanPkt;
enum TCanChannel {
CANch1 = 0,
CANch2 = 1,
};
enum TLinChannel {
LINch1 = 0,
LINch2 = 1,
#if defined MOBICAR_3
LINch3 = 2,
#endif
};
enum TGuardEvents {
geSetSysMode = 0, // события о смене режима Системы
geRESET = 0, // событие сброс по Питанию
geTEST = 1, // включился режим Теста
geSERVICE = 2, // включился режим Автосервис
geDISARM = 3, // включился режим Вне Охраны
geHIJACK = 4, // включился режим Антизахват
geARM = 5, // включился режим Охрана
geGM6 = 6, // резерв
geGM7 = 7, // резерв
aseSetMode = 8, // события о смене режима Автозапуска
aseIDLE = 8, // Дежурный режим
aseREADY = 9, // Включение поддержки зажигания
asePRESTART_WaitForIgnOn = 10, // Подготовка к запуску двигателя: Ожидание включения Зажигания
asePRESTART_WaitForIgnOff = 11, // Подготовка к запуску двигателя: Ожидание выключения Зажигания
aseCRANK = 12, // Запуск двигателя (стартер)
asePRESUPPORT = 13, //
aseSUPPORT = 14, // Поддержка зажигания после запуска
asePITSTOP = 15, // Режим PITSTOP
aseSTOP = 16, // Режим STOP
aseISOFF = 17, // Режим ISOFF
aseDoorWag = 18, // Махание дверью
aseStopDoorWag = 19, // Остановка процесса махания дверью
aseSetIDLE = 20, // Переход в дежурный режим
aseSetREADY = 21, // Переход в режим поддержки зажигания
aseSetPITSTOP = 22, // Переход в режим PITSTOP
aseSetPRESTART = 23, // Переход в режим подготовки к запуску двигателя
aseSetSUPPORT = 24, // Переход в режим поддержки зажигания
aseSetSTOP = 25, // Остановка двигателя
aseSetISOFF = 26, // Выключение поддержки зажигания
aseLauncher = 27, // Мотор запущен внешним запуском
asePreHeater = 28, // Предпусковой подогреватель включен
aseASM21 = 29, // резерв
aseReloadTimer = 30, // продление/перезагрузка времени режима
aseCommandError = 31, // ошибка выполнения команды или не возможность выполнить команду
// Общие события
geLocked = 32, // ЦЗ закрыт
geUnLocked = 33, // ЦЗ открыт
geBlockageOff = 34, // Блокировка выключена
geBlockageOn = 35, // Блокировка включена
geReservationOff = 36, // Резервирование выключено
geReservationOn = 37, // Резервирование включено
geEngineStopped = 38, // Двигатель остановился
geEngineRuns = 39, // Двигатель завелся
geTurboTimerEnd = 40, // Турботаймер завершился
geTurboTimerStart = 41, // Турботаймер запустился
gePanicOff = 42, // выключился режим Паника
gePanicOn = 43, // включился режим Паника
geArmDefeatZone = 44, // оповещение об открытых зонах во время постановки в Охрану
geAlarmOff = 45, // выключился режим Тревоги
geAlarmOn = 46, // включить тревогу снова
geDoorsAlarm = 47, // включилась Тревога по дверям (салону)
geTrunkAlarm = 48, // включилась Тревога по багажнику
geHoodAlarm = 49, // включилась Тревога по капоту
geIgnAlarm = 50, // включилась Тревога по зажиганию
geShockAlarm = 51, // включилась Тревога по датчику Удара
geResetAlarm = 52, // включилась Тревога по сбросу Питания
geDoorsDefeated = 53, // отключилась охранная зона по двери
geTrunkDefeated = 54, // отключилась охранная зона по багажнику
geHoodDefeated = 55, // отключилась охранная зона по капоту
geIgnDefeated = 56, // отключилась охранная зона по зажиганию
geShockDefeated = 57, // отключилась охранная зона по датчику Удара
geTrunkOpened = 58, // багажник открыт
geTrunkClosed = 59, // багажник закрыт
geShockNotify = 60, // предупреждение по датчику Удара
geShockArmOff = 61, // оперативное отключение зоны датчика Удара
geCarOwnerCall = 62, // вызов владельца автомобиля
geTiltAlarm = 63, // включилась Тревога по датчику Наклона
geTiltDefeated = 64, // отключилась охранная зона по датчику Наклона
geValetArm = 65, // событие поставить в Охрану в режиме Автосервис
geValetDisarm = 66, // событие снять с Охраны в режиме Автосервис
geAlarmEnd = 67, // событие прекращения тревоги
geTrunkUnLock = 68, // багажник отпирается или отперт
geTrunkLock = 69, // багажник запирается или заперт
geImHereOff = 70, // выключился механизм поиска Автомобиля на стоянке
geImHereOn = 71, // включился механизм поиска Автомобиля на стоянке
geMotionAlarm = 72, // включилась Тревога по датчику Перемещений
geMotionDefeated = 73, // отключилась охранная зона по датчику Перемещений
geArmed = 74, // Система встала под Охрану
geArmReturnOff = 75, // Перепостановка отключена
geArmReturnOn = 76, // Активирован режим перепостановки
geAux1Off = 77, // Доп.канал #1 выключен
geAux1On = 78, // Доп.канал #1 включен
geAux2Off = 79, // Доп.канал #2 выключен
geAux2On = 80, // Доп.канал #2 включен
geAux3Off = 81, // Доп.канал #3 выключен
geAux3On = 82, // Доп.канал #3 включен
geSensorAlarm = 83, // тревога по внешнему Сенсору
geSensorDefeated = 84, // отключилась охранная зона по входу от внешнего Сенсора
geHandsfreeDisabled = 85, // сообщение о временном запрете Автопостановки/Автоснятия
geHandsfreeEnabled = 86, // сообщение о разрешении Автопостановки/Автоснятия
geValetDisabledByImm = 87, // включение режима Автосервис заблокировано по причине активированного Иммобилайзера
geDisarmDisabledByTag = 88, // снятие с Охраны заблокировано по причине отсутствия Метки
geUnTrunkDisabledByTag = 89, // отпирание багажника заблокировано по причине отсутствия Метки
geImmoIndicationStart = 90, // индикация включенного иммобилайзера
geSensorNotify = 91, // предупреждение по внешнему Сенсору
geDrivingEnabled = 92, // поездка разрешена (иммобилайзер был отключен ПИН кодом)
geTripFinish = 93, // Поездка закончилась
geTripStart = 94, // Поездка началась
geTripPaused = 95, // Поездка приостановилась
// Команды Брелока (176+)
bcSendState = 0xB0, // Выслать текущий режим Системы (она же ресинхронизация)
bcChangeSoundMode, // Изменение режима выдачи звуков
bcChangeShockMode, // Изменение режима работы датчика Удара
bcChangeAutomatics, // Изменения в режимах работы Автоматических запусков
bcChangeInternetOption, // Изменения в режиме работы INTERNET опции
bcProgMenuEnter, // Перевести брелок в меню программирования
bcProgMenuExit, // Выход из меню программирования Брелока
vmShowPinCode, // Показать на индикаторе текущее значение ПИН-кода
bcProgMenu2, // Переход к меню 2
bcBleMenuEnter, // Переход к меню спаривания BLE
bcHandsfreeModeChange, // Изменение режима работы "Свободных рук"
geDEBUG = 0xFE,
geNONE = 0xFF // нет события, т.е. его не нужно никуда отправлять
};
union TDiagnosticTroubleCode {
uint16_t B1B0;
uint8_t Byte[2];
struct {
uint8_t B0;
uint8_t B1;
} __attribute__((packed));
struct {
uint16_t X:4;
uint16_t N:2;
uint16_t K:2;
uint16_t Z:4;
uint16_t Y:4;
} __attribute__((packed));
} __attribute__((packed));
#endif /* COMMON_COMMONTYPES_H_ */

329
libs/IO.h Normal file
View File

@@ -0,0 +1,329 @@
/*
* IO.h
*
* Created on: 11 июня 2015 г.
* Author: esaulenko
*/
#ifndef DRIVERS_IO_H_
#define DRIVERS_IO_H_
#include <cstdint>
#include "CommonTypes.h"
#include "Settings.h"
#include "Utils.h"
#if not defined CAN_FIRMWARE
#include "SysTimer.h"
#endif
typedef uint64_t TInpMask; // битовая маска логических входов
typedef uint64_t TOutMask; // битовая маска логических выходов
// макросы для более простого обращения к битовым маскам
#define oBIT(x) BIT64(CIO::x)
#define iBIT(x) BIT64(CIO::x)
class CIO
{
#define iPIN(x) (CSettings::x-CSettings::ipOFFSET)
#define oNAME(x) (CSettings::x-CSettings::oOFFSET)
#define iNAME(x) (CSettings::x-CSettings::iOFFSET)
public:
// Эта таблица источников для логических входов (функций)
#if defined MOBICAR_1_2
enum TInPins {
iRedBlack = iPIN(iRedBlack), // Pin_Door_I
iGreyBlack = iPIN(iGreyBlack), // Pin_Trunk_I
iBrownBlack = iPIN(iBrownBlack), // Pin_Hood_I
iGreen = iPIN(iGreen), // Pin_Ignition
iLBlueBlack = iPIN(iLBlueBlack), // Pin_Parking_I
iBlackWhite = iPIN(iBlackWhite), // Pin_Foot_I
iBlackPink = iPIN(iBlackPink), // Pin_RPM_I
iYellowBlue = iPIN(iYellowBlue), // Pin_OutRes2
iYellowWhite = iPIN(iYellowWhite), // Pin_OutRes1
ipCOUNT = CSettings::ipCOUNT, // Общее кол-во физических источников
iCAN = 0x7E, // берется из CAN шины
iNone = 0x7F // никуда не подключен
};
enum TOutPins {
oBrownGreen, // Pin_Ign_O
oBrownViolet, // Pin_Ign1_O
oBrownYellow, // Pin_Start_O
oBrownWhite, // Pin_Acc_O
oGreen, // Pin_LockRelay Relay3
oYellow, // Pin_UnlockRelay Relay4
oVioletYellow, // Pin_Light1Relay Relay1
oVioletBrown, // Pin_Light2Relay Relay2
oPink, // Pin_Relay5 Relay5
oBlue, // Pin_Immo_O
oBrown, // Pin_SirenOut
oYellowBlue, // Pin_OutRes2_O
oYellowWhite, // Pin_OutRes1_O
oOrange, // Kline1
oOrangeBlack, // KLine2
opCOUNT, // Общее кол-во физических выходов
oCAN = 31,
};
#elif defined MOBICAR_3 || defined MAGICAR_X
enum TInPins {
iRedBlack = iPIN(iRedBlack),
iGreyBlack = iPIN(iGreyBlack),
iBrownBlack = iPIN(iBrownBlack),
iGreen = iPIN(iGreen),
iLBlueBlack = iPIN(iLBlueBlack),
iBlackWhite = iPIN(iBlackWhite),
iBlackPink = iPIN(iBlackPink),
iYellowBlue = iPIN(iYellowBlue),
iYellowWhite = iPIN(iYellowWhite),
ipCOUNT = CSettings::ipCOUNT, // Общее кол-во физических источников
iCAN = 0x7E, // берется из CAN шины
iNone = 0x7F // никуда не подключен
};
enum TOutPins {
oGreenRelay,
oVioletRelay,
oYellowRelay,
oWhiteRelay,
oBrownGreen,
oBrownYellow,
oBrownViolet,
oBrownWhite,
oOrangeBreak, // разрыв Lin1
oBlue,
oBrown,
oYellowBlue, // вход/выход +/-
oYellowWhite, // вход/выход +/-
oGreen, // вход/выход
oBlackWhite, // вход/выход
oPinkBreak, // разрыв Lin2
oOrange, // Lin1
oPink, // Lin2
oPinkWhite, // Lin3
opCOUNT, // Общее кол-во физических выходов
oCAN = 31 // Выход на CAN-прошивку
};
#else
#error IO pins: unknown model!
#endif
enum TInputs {
iDoorDrv = iNAME(iDoorDrv),
iDoorFP = iNAME(iDoorFP),
iDoorRL = iNAME(iDoorRL),
iDoorRR = iNAME(iDoorRR),
iTrunk = iNAME(iTrunk),
iHood = iNAME(iHood),
iIgn = iNAME(iIgn),
iHBrake = iNAME(iHBrake),
iLamp = iNAME(iLamp),
iPark = iNAME(iPark),
iBrake = iNAME(iBrake),
iLeftTurnLight = iNAME(iLeftTurnLight),
iRightTurnLight = iNAME(iRightTurnLight),
iArm = iNAME(iArm),
iSensorAlarm = iNAME(iSensorAlarm),
iSensorNotify = iNAME(iSensorNotify),
iEngine = iNAME(iEngine),
iLock = iNAME(iLock),
iPreHeater = iNAME(iPreHeater),
iLowFuelLevel = iNAME(iLowFuelLevel),
iACC = iNAME(iACC),
iKeyIn = iNAME(iKeyIn),
iSpark = iNAME(iSpark),
iDoorsLamp = iNAME(iDoorsLamp),
iTrunkLamp = iNAME(iTrunkLamp),
iTrunkWindow = iNAME(iTrunkWindow),
iStartStop = iNAME(iStartStop),
iNeutral = iNAME(iNeutral),
iLauncher = iNAME(iLauncher),
iDisarm = iNAME(iDisarm),
iUnTrunk = iNAME(iUnTrunk),
iUnLock = iNAME(iUnLock),
iDevice1 = iNAME(iDevice1),
iDevice2 = iNAME(iDevice2),
iDevice3 = iNAME(iDevice3),
iDevice4 = iNAME(iDevice4),
iDevice5 = iNAME(iDevice5),
iDevice6 = iNAME(iDevice6),
iDevice7 = iNAME(iDevice7),
iDevice8 = iNAME(iDevice8),
iCOUNT = CSettings::iCOUNT,
iStateAtMt = 63 // особый вход: "трансмиссия автомат"
};
// Виртуальные выходы на исполнительные устройства или
// выход на устройство выполняющее определенную функцию
enum TOutputs {
// Неопределенные устройства
oDevice1 = oNAME(oDevice1), // 0
oDevice2 = oNAME(oDevice2), // 1
oDevice3 = oNAME(oDevice3), // 2
oDevice4 = oNAME(oDevice4), // 3
oDevice5 = oNAME(oDevice5), // 4
oDevice6 = oNAME(oDevice6), // 5
oDevice7 = oNAME(oDevice7), // 6
oDevice8 = oNAME(oDevice8), // 7
// Базовые устройства Охранной системы
oSiren = oNAME(oSiren), // 08 Сирена
oHorn = oNAME(oHorn), // 09 Клаксон
oLights = oNAME(oLights), // 10 Поворотники
oLamp = oNAME(oLamp), // 11 Головное освещение
oPassiveBlockage = oNAME(oPassiveBlockage), // 12 Пассивная блокировка (когда выключена, цепь разомкнута, блокировка включена)
oActiveBlockage = oNAME(oActiveBlockage), // 13 Активная блокировка (когда выключена, цепь замкнута, блокировка выключена)
oLockDoors = oNAME(oLockDoors), // 14 Запереть все двери
oUnlockDoors = oNAME(oUnlockDoors), // 15 Отпереть все двери
oUnlockDoorDrv = oNAME(oUnlockDoorDrv), // 16 Отпереть дверь водителя
oLockTrunk = oNAME(oLockTrunk), // 17 Запереть багажник
oUnlockTrunk = oNAME(oUnlockTrunk), // 18 Отпереть багажник
oLockHood = oNAME(oLockHood), // 19 Запереть Капот
oUnLockHood = oNAME(oUnLockHood), // 20 Отпереть капот
oCloseWindows = oNAME(oCloseWindows), // 21 Закрыть окна
oPreHeaterOn = oNAME(oPreHeaterOn), // 22 Включение предпускового подогревателя
oPreHeaterOff = oNAME(oPreHeaterOff), // 23 Выключение предпускового подогревателя
oImmOn = oNAME(oImmOn), // 24 Устройство включающее Иммобилайзер
oImmOff = oNAME(oImmOff), // 25 Устройство выключающее Иммобилайзер
oService = oNAME(oService), // 26 Устройство переводящее автомобиль в Сервисный режим
oDisarm = oNAME(oDisarm), // 27 Устройство осуществляющее снятие с Охраны (можно использовать как выход статической блокировки)
oArm = oNAME(oArm), // 28 Устройство осуществляющее постановку под Охрану (можно использовать как выход статической блокировки)
oAlarm = oNAME(oAlarm), // 29 Устройство осуществляющее включение тревоги (можно использовать как выход статической блокировки)
oAutoStart = oNAME(oAutoStart), // 30 Состояние Автозапуска
// Базовые устройства АвтоЗапуска (подменяют или имитируют присутствие водителя в автомобиле)
oDoorWag = oNAME(oDoorWag), // 31 Устройство махающее дверью
oIgn = oNAME(oIgn), // 32 Включение зажигания
oBrake = oNAME(oBrake), // 33 Педаль тормоза
oKeyIn = oNAME(oKeyIn), // 34 Ключ в замке
oAcc = oNAME(oAcc), // 35 Аксессуары
// oBrakeControl = oNAME(oBrakeControl), // 36 Отключение контроля педали тормоза
oAuxBrake = oNAME(oAuxBrake), // 37 Дополнительная линия педали тормоза
oAuxIgn = oNAME(oAuxIgn), // 38 Дополнительная линия зажигания
oSSButton = oNAME(oSSButton), // 39 Кнопка Старт/Стоп
oImmBypass = oNAME(oImmBypass), // 40 Обходчик встроенного иммобилайзера
oCrank = oNAME(oCrank), // 41 Стартер
oCrankDisable = oNAME(oCrankDisable), // 42 Блокировка Стартера
// Дополнительные
oLockIgn = oNAME(oLockIgn), // 43 Блокировка зажигания (когда включена, зажигание заблокировано)
oUnLockIgn = oNAME(oUnLockIgn), // 44 Разблокировка зажигания (когда включена, зажигание разблокировано)
oKLine1Relay = oNAME(oKLine1Relay), // 45 Устройство коммутирующее KLine интерфейс
oAux1 = oNAME(oAux1), // 46 Доп.канал #1
oAux2 = oNAME(oAux2), // 47 Доп.канал #2
oAux3 = oNAME(oAux3), // 48 Доп.канал #3
oEmergencyBraking=oNAME(oEmergencyBraking), // 49 Выход сигнала экстренного торможения
oIllumination = oNAME(oIllumination), // 50 Выход сигнала вежливой подсветки
oFoldMirrors = oNAME(oFoldMirrors), // 51 Сложить зеркала
oUnfoldMirrors = oNAME(oUnfoldMirrors), // 52 Разложить зеркала
oCloseSunroof = oNAME(oCloseSunroof), // 53 Закрыть люк
oMoveSunroof = oNAME(oMoveSunroof), // 54 Сдвинуть люк
oHeatedSeats = oNAME(oHeatedSeats), // 55 Обогрев сидений
oTriggerDoors = oNAME(oTriggerDoors), // 56 Триггерная кнопка ЦЗ
oIgnSupport = oNAME(oIgnSupport), // 57 Состояние поддержки зажигания
oArmWithoutTag = oNAME(oArmWithoutTag), // 58 Состояние "Охрана без метки"
oHeatedWindows = oNAME(oHeatedWindows), // 59 Обогрев окон
oKLine2Relay = oNAME(oKLine2Relay), // 60 m34x46: Коммутация Lin2
oDVR = oNAME(oDVR), // 61 m34x46: Выход на видеорегистратор
// Общее кол-во виртуальных устройств
oCOUNT = CSettings::oCOUNT,
};
// режимы входов
enum TInputActiveState {
ActiveGND = 1 // Активное состояние, когда на входе GND
};
// режимы подтяжек входов
enum TInputPullupMode {
PullNone = 0,
PullDown = 2,
PullUp = 3,
};
#undef iPIN
#undef oNAME
#undef iNAME
#ifndef CAN_FIRMWARE
void Init(void);
void UpdateSettings(const uint idSettings);
// проверка, что вход (физический) используется
static bool IsInputMapped(TInPins aPhInput);
// чтение и обработка мгновенных состояний входов для получения устойчивых физических состояний
uint32_t ReadInputPins(void);
// Конвертирование переданных физический состояний (REMAP) в соответствующие логические состояния
TInpMask RemapInputs(uint32_t iPins);
// установка физических выходов
void SetOutPhys(const TOutPins pin, const bool state);
// Установка логических выходов.
// Возвращает:
enum TSetOutputResult : uint {
soNone = 0, // нет такого выхода или он никуда не назначен
soExist = 1, // Выход назначен, но состояние не изменилось
soChanged = 2 // выход назначен и состояние было изменено
};
TSetOutputResult SetOutput(const TOutputs aOutput, const bool state);
// Запрос текущего состояния логического выхода
inline bool GetOutput(const TOutputs Output) const {return bbRAM(oStates,Output);};
// Вернуть состояние логических выходов (функций выходов)
inline TOutMask GetOutputs(void) const {return oStates;}
// Вернуть состояние логических входов (функций входов)
inline TInpMask GetInputs(void) const {return iStates;}
// Вернуть состояние физических выходов
inline uint32_t GetOutPhys(void) const {return opStates;}
inline bool GetOutPhys(const TOutPins pin) const
{ return GetOutPhys() & BIT(pin); }
// петля "тип коробки"
static bool StateAtMt(void);
private:
TOutMask oStates; // сохраненные состояния логических выходов (всех функций выходов)
TInpMask iStates; // сохраненные состояния логических входов (всех функций входов)
uint32_t ipStates, ipTemp; // физические состояния входов, очищенные от дребезга...
uint32_t opStates; // физические состояния выходов
struct TInputPin {
TimerMs Timer;
uint16_t TimeOut;
uint8_t Stage;
};
TInputPin iPin[ipCOUNT];
// получение мгновенных состояний со входов
static uint32_t GetInputPins(void);
// управляет состояниями подтяжек на входах
static void SetPullInput(TInPins Input, TInputPullupMode Mode);
inline void ClrOutputState(TOutputs Output) {bbRAM(oStates,Output) = 0;};
inline void SetOutputState(TOutputs Output) {bbRAM(oStates,Output) = 1;};
#endif // ! CAN_FIRMWARE
};
// глобальный объект портов ввода-вывода
extern CIO gIO;
#endif /* DRIVERS_IO_H_ */

212
libs/LinBus.h Normal file
View File

@@ -0,0 +1,212 @@
/*
* LinBus.h
*
* Created on: 17 дек. 2015 г.
* Author: esaulenko
*/
#ifndef DRIVERS_LINBUS_H_
#define DRIVERS_LINBUS_H_
#ifndef CAN_FIRMWARE
#include "KLineDrv.h"
#include "ImoDrv.h"
#include "Buffer.h"
#include "SysTimer.h"
#include "scmRTOS/scmRTOS.h"
extern CLin LinBus1;
extern CLin LinBus2;
extern CLin LinBus3;
union TLinInit;
#endif // CAN_FIRMWARE
#include "LinFrame.h"
class CLin
{
public:
enum TLinMode {
Mode_RawNoParity, // без стандарта, принимает-передаёт любые пакеты (без чётности)
Mode_Master, // LIN-мастер
Mode_Slave, // LIN-слейв
Mode_RawEvenParity, // без стандарта, байты с проверкой на чётность
Mode_RawOddParity, // без стандарта, байты с проверкой на нечётность
Mode_Raw9bit, // без стандарта, в байте 9 бит данных без чётности
Mode_RawIgnoreError, // без стандарта, принимаются байты без чётности, стоп-бита и т.д.
Mode_RawStop2bit, // без стандарта, 2 стоп-бита
Mode_ImoImi, // протокол Toyota (старый), 48.8 бит/сек, 16 бит данных
Mode_ImoRenault, // протокол Renault, 81,4 бит/с
Mode_ImoImi2, // протокол Toyota (новый), 195.3 бит/сек, 32 бита данных
Mode_FordDstTx, // протокол Ford DST80 (ШИМ, 1 бит = 1 мс / 0,5 мс)
Mode_FordUartRx, // протокол Ford (UART 15625 бит/с, 384 мкс между байтами)
Mode_Haval, // протокол с импульсами подтверждения (фильтрация/генерация)
Mode_FordDstInversion, // протокол Ford DST80 (ШИМ, 1 бит = 1 мс / 0,5 мс, ИНВЕРСНЫЙ сигнал)
};
#ifndef CAN_FIRMWARE
CLin(const KLineHw & cfg) : _drv(cfg, this), _imoDrv(this, cfg)
{}
uint32_t Init(const TLinInit & init);
// Для режима Haval
void InitEXTI(void);
void DeinitEXTI(void);
void EdgeRcv(const bool newVal);
void CheckTimeout(void);
int32_t GetFrame(TLinFrame & aFrame);
uint32_t SendFrame(const TLinFrame & aFrame);
void Sleep(const bool sleepEnable);
// вызывается из обработчиков прерываний:
// приём/передача UART
void IrqUart(void)
{ _drv.IrqProcess(); }
// передача UART по таймеру
uint32_t IrqTimerSend(void)
{ return _drv.IrqTimerSend(); }
// фронт в режиме IMO/IMI
void IrqImoEdge(const bool val)
{
Sleep(false);
if (_mode == Mode_Haval)
EdgeRcv(val);
else
_imoDrv.rx.EdgeRcv(val);
}
// таймер передачи в режиме IMO/IMI (только для LIN1)
void IrqImoSend(void)
{ _imoDrv.tx.IrqSetNextBit(); }
// управление выходом напрямую, как GPIO
void SetOutput(const bool setZero);
private:
CKLineDrv _drv;
CImoDrv _imoDrv;
// вызывается из прерывания по приёму
void DataRcvd(uint16_t data);
void BreakRcvd(void);
void ErrorRcvd(void);
// вызывается из прерываний IMO/IMI
void DataImiRcvd(const uint8_t * data, uint32_t data_len);
// вызывается из прерывания по передаче
bool IsTxData(void)
{ return _tx_buf.Avail() > 0; }
uint16_t GetTxData(void)
{ return _tx_buf.Get(); }
void TxComplete(void);
friend CKLineDrv;
friend CImoDrv;
TLinMode _mode;
union {
bool _mode9bit = false;
bool _InverseSignal; // инверсия входного сигнала
};
// не-UART протоколы на таймере
bool isCustomMode(void) const
{
return _mode == Mode_ImoImi ||
_mode == Mode_ImoImi2 ||
_mode == Mode_ImoRenault ||
_mode == Mode_FordDstTx ||
_mode == Mode_FordDstInversion;
}
enum {
State_NoInit,
State_BusOff,
State_Idle,
State_WaitSync,
State_WaitId,
State_WaitData,
State_SlaveTxData,
} _state = State_NoInit;
TLinFrame _rx_frame;
TimerMs _rx_tmr;
uint32_t _rx_timeout;
TimerMs _sleep_tmr;
uint32_t _sleep_timeout;
uint8_t _bytecnt; // счетчик байт для Mode_Haval
uint8_t _bytes_noack; // кол-во байт без подтверждения для Mode_Haval
uint8_t _bytes_ack; // кол-во байт c подтверждением для Mode_Haval
// TimerUs _ack_tmr; // таймер для генерации импульов Mode_Haval
uint8_t _bit_length_us;
uint16_t _ack_pause_us;
bool FrameToRxQueue(void);
CircularBuffer<TLinFrame, 8> _rx_queue;
CircularBuffer<uint16_t, 16> _tx_buf; // буфер на передачу
TLinFrame _tx_fr_buf[16]; // кадры для передачи slave'ом
TLinFrame*_tx_fr_cur = _tx_fr_buf; // текущий передающийся кадр
bool StartSlaveTx(uint8_t id); // функция отправки этого кадра
TLinFrame * getTxFrame(void) // забрать фрейм из буфера (для imo_drv)
{
for (auto & it: _tx_fr_buf)
if (it.data_len > 0)
return &it;
return nullptr;
}
// возвращает номер канала
inline TLinChannel Instance(void) const
{
#ifdef MOBICAR_3
if (this == &LinBus3)
return LINch3;
#endif
if (this == &LinBus2)
return LINch2;
return LINch1;
}
#endif // not CAN_FIRMWARE
};
union TLinInit
{
struct TLin
{
uint16_t baudrate;
CLin::TLinMode mode;
uint32_t rxTimeout;
uint32_t sleepTimeout;
}Lin;
struct THaval
{
uint16_t baudrate;
CLin::TLinMode mode;
uint16_t rxTimeout;
uint32_t sleepTimeout;
uint8_t bytes_noack; // кол-во байт без подтверждения
uint8_t bytes_ack; // кол-во байт c подтверждением
uint16_t ack_pause_us; // пауза в us перед ack в режиме генерации (0-режим фильтрации)
}Haval;
};
#endif /* DRIVERS_LINBUS_H_ */

81
libs/LinFrame.h Normal file
View File

@@ -0,0 +1,81 @@
/*
* LinFrame.h
*
* Created on: 26 дек. 2015 г.
* Author: esaulenko
*/
#ifndef DRIVERS_LIN_LINFRAME_H_
#define DRIVERS_LIN_LINFRAME_H_
#include <cstdint>
#include "Utils.h"
class TLinFrame
{
private:
enum { MaxDataLen = 16, };
public:
TLinFrame():
data_len(-1) // изначально буфер пустой
{}
uint8_t id;
int8_t data_len; // знак используется при приёме
uint16_t data[MaxDataLen + 1]; // data + chksum
// посчитать контрольную сумму по стандарту 1.1 (без ID) или по стандарту 2.0 (c ID)
uint8_t CalcChksum (bool new_mode)
{
data_len = MIN (data_len, MaxDataLen);
uint32_t chksum = new_mode ? id : 0;
for (int i = 0; i < data_len; i++)
{
chksum += data[i];
if (chksum > 0xFF)
chksum -= 0xFF;
}
return ~ chksum;
}
// добавить контрольную сумму в пакет
void AddChksum (bool new_mode)
{ data[data_len] = CalcChksum (new_mode); }
// проверить контрольную сумму пакета
bool IsChksumCorrect (bool new_mode)
{ return data[data_len] == CalcChksum (new_mode); }
// посчитать контрольные (старшие) биты в идентификаторе
void CalcIdChksum (uint8_t aId)
{
// byte = p7 p6 b5..b0
// P6 = b0 ^ b1 ^ b2 ^ b4
// P7 = ~ (b1 ^ b3 ^ b4 ^ b5)
uint8_t P6 = (aId >> 0) ^ (aId >> 1) ^ (aId >> 2) ^ (aId >> 4);
uint8_t P7 = (aId >> 1) ^ (aId >> 3) ^ (aId >> 4) ^ (aId >> 5);
P6 = ( P6 & 0x01) << 6;
P7 = ((~P7) & 0x01) << 7;
id = P7 | P6 | (aId & 0x3F);
}
// скопировать данные в кадр (до 8 байт)
template <int N>
inline void SetData (const char (&data_str)[N])
{
data_len = MIN (N - 1, MaxDataLen);
for (int i = 0; i < data_len; i++)
data[i] = (uint8_t)data_str[i];
}
};
#endif /* DRIVERS_LIN_LINFRAME_H_ */

9
libs/ModelName.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#if defined MOBICAR_1_2
#define M_NAME "M2_"
#elif defined MOBICAR_3
#define M_NAME "M3_"
#endif

166
libs/Periodic.h Normal file
View File

@@ -0,0 +1,166 @@
/*
* Periodic.h
*
* Создан: 09 окт. 2015 г.
* Автор: esaulenko
*
* Изменен: 21 ноя. 2019 г.
* Автор: gavrilov
*/
#ifndef PERIODIC_H_
#define PERIODIC_H_
#include <cstdint>
#include <cstddef>
#include "SysTimer.h"
#include "Utils.h"
template <uint nTasks>
class CPeriodic
{
private:
typedef void (* TPeriodicTask) (TCanFwMem * apMem);
public:
// добавить новую функцию для периодического вызова. Обычно выполняется один раз.
void AddTask(const uint iTask, TPeriodicTask TaskHandler = nullptr, const uint32_t msTime = 0)
{
if (iTask < nTasks)
{
Tasks[iTask].Handler = TaskHandler;
SetTimeout(iTask, msTime);
}
}
// Установить время, через которое надо будет вызвать периодическую функцию
void SetTimeout(const uint iTask, uint32_t msTime = 0)
{
if (iTask < nTasks)
{// индекс не превышает размер массива
// Если вызов происходит из <Process>, то местный таймер уже был сброшен.. и, соответственно, нужно только обновить
// значение периода.. а пересчет минимального времени, также произойдет при выходе из <Process>..
// При вызове же вне <Process>, ни местный таймер не сбрасывается, ни пересчет периода не происходит..
if (!Mutex)
{// При вызове вне <Process>:
// 1. Нужно обязательно вызывать метод <SetNextCall>, т.к. следующий период может как удлиниться, так и укоротиться.
// 2. А для того, чтобы метод <SetNextCall> правильно выставил время следующего вызова <Process>,
// требуется пересчитать все текущие периоды с учетом набега времени.
// 3. А раз нам требуется пересчитать все текущие периоды, то значит мы должны пересбросить местный
// таймер отсчета времени.
// 4. Однако, т.к. отсюда нельзя вызывать обработчики, то тем периодам, что окончились здесь,
// приходится ставить минимальное значение =1, чтобы обеспечить как можно скорее вызов обработчика <Process>.
//
auto elapsed = Timer.Restart();
if (elapsed)
for (auto & Task: Tasks)
// Пройдемся по всем задачам..
if (Task.Timeout)
{
// task enabled
if (Task.Timeout > elapsed)
Task.Timeout -= elapsed;
else
// Отсюда мы не можем вызвать обработчик, поэтому просто ставим минимальное время..
Task.Timeout = 1;
}
}
if (Tasks[iTask].Handler == nullptr)
// Если обработчик неопределен.. остановить задачу..
msTime = 0;
// Установить время..
Tasks[iTask].Timeout = msTime;
// Всегда сбрасывать признак выполненной задачи, т.к. только-что для нее был выставлен новый период..
// ..следовательно, предыдущий период уже стал неактуальным..
Tasks[iTask].Done = false;
// Пересчитать интервалы..
if (!Mutex)
// ..здесь только для вызывов извне <Process>..
SetNextCall();
}
}
// остановить задачу
void Stop(const uint iTask)
{
if (iTask < nTasks)
{
Tasks[iTask].Timeout = 0;
Tasks[iTask].Done = false;
}
}
// проверить, что задача запущена
bool isActive(const uint iTask) const
{
if (iTask < nTasks)
if (Tasks[iTask].Handler != nullptr)
if (Tasks[iTask].Timeout)
return true;
return false;
}
private:
struct {
TPeriodicTask Handler = nullptr;
uint32_t Timeout = 0;
bool Done = false;
} Tasks[nTasks];
TimerMs Timer;
volatile bool Mutex = false;
// Обработчик, вызывается из PeriodicProcess()
void Process(TCanFwMem * apCanMemory)
{
auto elapsed = Timer.Restart();
if (elapsed)
{
// Сначала нужно обновить периоды всех периодических функций..
for (auto & Task: Tasks)
// Пройдемся по всем задачам..
if (Task.Timeout)
{
// task enabled
if (Task.Timeout > elapsed)
Task.Timeout -= elapsed;
else
{
Task.Done = true;
Task.Timeout = 0;
}
}
// Затем запустить все сработавшие задачи..
Mutex = true; // выставить признак того, что метод <SetTimeout> будет вызван из метода <Process>
for (auto & Task: Tasks)
// Пройдемся по всем задачам..
if (Task.Done)
{// Если задача сработала..
Task.Done = false;
if (Task.Handler != nullptr)
// task exist
Task.Handler(apCanMemory); // ..запустить ее
}
Mutex = false;
// Запустить перерасчет и установку минимального интревала времени для вызова следующей периодической функции
SetNextCall();
}
}
friend void PeriodicProcess(TCanFwMem * vars);
// Расчитать минимальное значение интервала времени для вызова следующей периодической функции
void SetNextCall(void)
{
uint32_t minTime = UINT32_MAX;
for (const auto & Task: Tasks)
if (Task.Timeout)
if (Task.Timeout < minTime)
minTime = Task.Timeout;
if (minTime == UINT32_MAX)
minTime = 0; // Остановить вызов <PeriodicProcess>
CoreFunc->SetPeriod(minTime);
}
};
#endif /* PERIODIC_H_ */

67
libs/Settings.cpp Normal file
View File

@@ -0,0 +1,67 @@
/*
* Settings.cpp
*
* Created on: 12 мая 2015 г.
* Author: esaulenko
*/
#include "Settings.h"
#include "IO.h"
#include "Utils.h"
#include "CanFwInterface.h"
// строки с названиями настроек
#define SETTING(...)
#define SETTING_CAN(...)
#define SETTING_RSRV(...)
#define SETTING_NAME(name, string) \
__attribute__ ((section(".SettingsVarName"))) \
static const char name ## String[] = string;
#include SRC_SETTINGS
#undef SETTING
#undef SETTING_RSRV
#undef SETTING_ALIAS
#undef SETTING_CAN
#undef SETTING_NAME
// таблица с настройками CAN-прошивки
__attribute__ ((section(".SettingsTable")))
const CSettings::TCANSettingsTable CSettings::CanSettingsTable = {
#define SETTING(name, attr, type, def_val...) \
name, kind_ ## type, attr, sizeof(THeader)+sizeof(type), def_val,
#define SETTING_CAN(name, attr, type, def_val, description) \
name, kind_ ## type, attr, sizeof(THeader)+sizeof(type), def_val,
#define SETTING_RSRV(...) // не используется
#define SETTING_NAME(name, string) \
name, 0x1F, NotFixed, sizeof(THeader)+sizeof(char*), name ## String,
#include SRC_SETTINGS
// 0xffff //LastVal
CSettings::LastVal
};
#undef SETTING
#undef SETTING_RSRV
#undef SETTING_ALIAS
#undef SETTING_CAN
#undef SETTING_NAME
__attribute__ ((section(".SettingsCanName")))
const char * const CSettings::CanSettingsName[] = {
#define SETTING(...) // names not used
#define SETTING_CAN(name, attr, type, def_val, description) description,
#define SETTING_RSRV(...) // не используется
#define SETTING_NAME(...) // не используется
#include SRC_SETTINGS
};
#undef SETTING
#undef SETTING_RSRV
#undef SETTING_ALIAS
#undef SETTING_CAN
#undef SETTING_NAME

267
libs/Settings.h Normal file
View File

@@ -0,0 +1,267 @@
/*
* Settings.h
*
* Created on: 12 мая 2015 г.
* Author: esaulenko
*/
#ifndef COMMON_SETTINGS_H_
#define COMMON_SETTINGS_H_
#include "CommonTypes.h"
#include "source/SourcePath.h"
#ifdef SRC_TYPES
#include SRC_TYPES
#endif
class CSettings
{
public:
// глобальная структура с настройками
struct TSettings
{
#define SETTING(...) // не используется
#define SETTING_CAN(name, attrib, type, ...) type name;
#define SETTING_RSRV(...) // не используется
#define SETTING_NAME(...) // не используется
#include SRC_SETTINGS
} __attribute__((packed));
#undef SETTING
#undef SETTING_RSRV
#undef SETTING_ALIAS
#undef SETTING_CAN
#undef SETTING_NAME
// объявляем номера настроек. этот enum может расти только вниз!
enum TSettingsID : uint16_t
{
#define SETTING(name, ...) name,
#define SETTING_RSRV(name) name,
#define SETTING_ALIAS(name) name,
#include "SettingsTable.h" // настройки ядра
CanSettingsStart = 0x600, // отсюда начинаются настройки CAN-прошивки (ПРИЧЕМ, самой 0x600 не может быть!!! т.к. это enum)
#define SETTING(name, ...) // не используется
#define SETTING_RSRV(name) name,
#define SETTING_CAN(name,...) name,
#define SETTING_NAME(...) // не используется
#include SRC_SETTINGS // собственные настройки CAN-прошивки
LastVal = 0x7FF // последний параметр
};
#undef SETTING
#undef SETTING_RSRV
#undef SETTING_ALIAS
#undef SETTING_CAN
#undef SETTING_NAME
// значения по умолчанию
enum DefaultValues {
minTimeZone = -9, // значение <-9> из-за ограничения при ручной установке пояса с брелока
defTimeZone = 0,
maxTimeZone = 12,
defClockSyncMode = 2,
maxClockSyncMode = 2,
defTimeZoneSyncMode = 2,
maxTimeZoneSyncMode = 2,
defLightsAutoStartMode = 2,
maxLightsAutoStartMode = 2,
defIlluminationMode = 0,
maxIlluminationMode = 3,
defLockByDriveMode = 0,
maxLockByDriveMode = 3,
defUnlockByParkMode = 0,
maxUnlockByParkMode = 2,
defArmReturnTimeIndex = 0,
minPlafondAlarmDelay = 1,
defPlafondAlarmDelay = 20,//60,
maxPlafondAlarmDelay = 120,
minDoorsLampDeciseconds = 0,
defDoorsLampDeciseconds = 30,
maxDoorsLampDeciseconds = 100,
minTrunkLampDeciseconds = 0,
defTrunkLampDeciseconds = 30,
maxTrunkLampDeciseconds = 100,
minAlarmDoorsDeciseconds = 0,
defAlarmDoorsDeciseconds = 5, // 0.5сек по умолчанию
maxAlarmDoorsDeciseconds = 50, // 5сек максимум
minAlarmTrunkDeciseconds = 0,
defAlarmTrunkDeciseconds = 5, // 0.5сек по умолчанию
maxAlarmTrunkDeciseconds = 100, // 10сек максимум
minKillEngineDeciseconds = 10, // 1.0сек минимум
defKillEngineDeciseconds = 0x80, // по умолчанию, выключено
maxKillEngineDeciseconds = 127, // 12.7сек максимум
defTurboTimerIndex = 0,
minReadyMinutes = 1,
defReadyMinutes = 2,
maxReadyMinutes = 8,
minSupportMinutes = 10,
defSupportMinutes = 20,
maxSupportMinutes = 60,
defPitStopTimeIndex = 1,
minPreHeaterMinutes = 1,
defPreHeaterMinutes = 10,
maxPreHeaterMinutes = 60,
defSetReadyMode = 0,
maxSetReadyMode = 2,
minManualAttempts = 1,
defManualAttempts = 1,
maxManualAttempts = 3,
defClrReadyMode = 0,
maxClrReadyMode = 1,
defPrestartSSB = 0,
maxPrestartSSB = 3,
defStopSSB = 0,
maxStopSSB = 3,
minCrankDelaySeconds = 1,
defCrankDelaySeconds = 3,
maxCrankDelaySeconds = 20,
minAutoStartBatteryLevel = 108,
defAutoStartBatteryLevel = 110|0x80, // выключено по-умолчанию
maxAutoStartBatteryLevel = 126,
minAutoStartTemperature = -30,
defAutoStartTemperature = 0-128, // выключена по-умолчанию
maxAutoStartTemperature = 60,
defDailyRunCountIndex = 0,
defAutomaticsPeriodIndex = 0,
defAutomaticsLimitIndex = 0,
minEngineStartPercent = 40/2,
defEngineStartPercent = 70/2,
maxEngineStartPercent = 100/2,
minEngineRunPercent = 30/2,
defEngineRunPercent = 60/2,
maxEngineRunPercent = 80/2,
minTurboTimerPercent = 150/2,
defTurboTimerPercent = 300/2,
maxTurboTimerPercent = 350/2,
minExternalHeatersTemperature = -20,
defExternalHeatersTemperature = 0-128, // выключена по-умолчанию
maxExternalHeatersTemperature = 20,
maxExternalTemperatureSensorType = 1,
defEmergencyBraking = 2,
maxEmergencyBraking = 2,
maxShockSensTable = 1,
minWaitAnswerTimeout = 5,
defWaitAnswerTimeout = 20,
maxWaitAnswerTimeout = 60,
minCallEndTimeout = 5,
defCallEndTimeout = 10,
maxCallEndTimeout = 60,
minTripEndTimeout = 5,
defTripEndTimeout = 15,
maxTripEndTimeout = 60,
minLowBatteryVoltage = 110,
defLowBatteryVoltage = 118,
maxLowBatteryVoltage = 125,
};
private:
// заголовок таблицы настроек
struct THeader
{
uint16_t ID :11; // идентификатор. Erase=0x000; Core=[0x001..0x5FF]; CanFw=[0x601..0x7FE]; LastVal=0x7FF
uint16_t Kind : 5; // тип данных, см. SettingKind
uint8_t Fixed : 1;
uint8_t Len : 7; // длина с учётом заголовка
// uint8_t Data[0];
bool operator == (const THeader & Header) const // fixed не проверяется!
// { return (ID == Header.ID) && (Kind == Header.Kind) && (Len == Header.Len); }
// { return (*(uint16_t*)this == *(uint16_t*)&Header) && (Len == Header.Len); }
{ return (*(uint16_t*)this == *(uint16_t*)&Header); } // и длина не проверяется!
} __attribute__ ((packed)); // sizeof() = 3
enum {
minRecordSize = sizeof(THeader)+1,
maxRecordSize = sizeof(THeader)+124 // 127 = 3+124 - самый максимум, т.к. Len = 7 бит.
};
// список допустимых типов данных.
// важно! при добавлении новых необходимо расширять список!
enum SettingKind // 0..31
{
kind_bit_t,
kind_uint8_t,
kind_uint16_t,
kind_uint32_t,
kind_int8_t,
kind_int16_t,
kind_int32_t,
kind_array_t,
kind_TInputPinSettings = kind_array_t,
kind_TInputSettings = kind_array_t,
kind_TSequence = kind_array_t,
kind_TCanOutMask = kind_array_t,
kind_uint64_t = kind_array_t,
kind_TKeyAES = kind_array_t,
kind_TVehicleID = kind_array_t,
kind_TStartTimerSetting = kind_array_t,
kind_TImmoKey = kind_array_t,
kind_TPhoneNumber = kind_array_t,
kind_TModemAPN = kind_array_t,
kind_TModemLogin = kind_array_t,
kind_TModemPassword = kind_array_t,
kind_TTagRSSI = kind_array_t,
kind_SettingName = 0x1F // спецзначение - указатель на описание настройки в CAN-прошивке
};
enum SettingAttr
{
NotFixed = 0,
Fixed = 1,
};
// Подбор ближайшего множителя к указанным милисекундам: MUL = ((2^p - 1)*2^5) + m*2^p = 2^(p+5) - 2^5 + m*2^p = (m + 2^5)*2^p - 2^5
static constexpr uint8_t qMS(int ms, int p = 0)
{ return ms < ((127<<p)-64)/2 ? p*32+((2*ms+64-(63<<p))>>(p+1)) : p < 7 ? qMS(ms, p+1) : 0xFF; }
public:
// таблица с настройками CAN-прошивки
struct TCANSettingsTable
{
#define SETTING(name, attr, type, ...) \
THeader hdr_ ## name; type name;
#define SETTING_CAN(name, attr, type, ...) \
THeader hdr_ ## name; type name;
#define SETTING_RSRV(...) // не используется
#define SETTING_NAME(name,string) \
THeader hdr_ ## name ## Str; const char * p ## name ## Str;
#include SRC_SETTINGS
#undef SETTING
#undef SETTING_RSRV
#undef SETTING_ALIAS
#undef SETTING_CAN
#undef SETTING_NAME
uint16_t last_val;
} __attribute__ ((packed));
// таблица с настройками CAN-прошивки
static const TCANSettingsTable CanSettingsTable;
// таблица с названиями полей CAN-прошивки
static const char * const CanSettingsName[];
};
#endif // COMMON_SETTINGS_H_

687
libs/SettingsTable.h Normal file
View File

@@ -0,0 +1,687 @@
// таблица с используемыми настройками
// выше должно быть определение того, какие поля используются
//#define SETTING(name, attrib, type, def_val)
// при добавлении новых типов данных необходимо расширить enum SettingKind
// SETTING_RSRV позволяет сделать "дырки" в номерах настроек
// если не определена, значит, она не используется
#ifndef SETTING_RSRV
#define SETTING_RSRV(name)
#endif
// SETTING_ALIAS позволяет задавать альтернативные имена для настроек
#ifndef SETTING_ALIAS
#define SETTING_ALIAS(alt_name)
#endif
SETTING_RSRV(Erased = 0) // нулевая настройка используется при удалении какого-либо идентификатора.
// настройки физических входов: 1..9 + 1 резерв
SETTING (iRedBlack, NotFixed, TInputPinSettings, {50, 3, 0})
SETTING (iGreyBlack, NotFixed, TInputPinSettings, {50, 3, 0})
SETTING (iBrownBlack, NotFixed, TInputPinSettings, {50, 3, 0})
SETTING (iGreen, NotFixed, TInputPinSettings, {50, 0, 0})
SETTING (iLBlueBlack, NotFixed, TInputPinSettings, {50, 1, 0})
SETTING (iBlackWhite, NotFixed, TInputPinSettings, {50, 0, 0})
SETTING (iBlackPink, NotFixed, TInputPinSettings, {50, 1, 0})
SETTING (iYellowBlue, NotFixed, TInputPinSettings, {50, 1, 0})
SETTING (iYellowWhite, NotFixed, TInputPinSettings, {50, 1, 0})
#ifndef ipFIRST
#define ipFIRST iRedBlack
#endif
SETTING_ALIAS(ipLAST)
SETTING_ALIAS(ipOFFSET = ipFIRST)
SETTING_ALIAS(ipCOUNT = (ipLAST-ipFIRST))
SETTING_RSRV(ReservedPins = 10)
/* Значения по-умолчанию:
Connector input wires table for FW rev 198:
Red-black wire Doors input (active low)
Grey-black wire Trunk input (active low)
Brown-black wire Hood input (active low)
Green wire Ignition input (active high)
Blue-black wire Handbrake/parking input (active low)
Black-white wire Brake input (active high)
Black-pink wire Tachometer input
*/
// настройки логических входов - 11..74
// Состояние неопределенных устройств (объектов)
SETTING (iDevice1, NotFixed, TInputSettings, {CIO::iNone, 0})
SETTING (iDevice2, NotFixed, TInputSettings, {CIO::iNone, 0})
SETTING (iDevice3, NotFixed, TInputSettings, {CIO::iNone, 0})
SETTING (iDevice4, NotFixed, TInputSettings, {CIO::iNone, 0})
SETTING (iDevice5, NotFixed, TInputSettings, {CIO::iNone, 0})
SETTING (iDevice6, NotFixed, TInputSettings, {CIO::iNone, 0})
SETTING (iDevice7, NotFixed, TInputSettings, {CIO::iNone, 0})
SETTING (iDevice8, NotFixed, TInputSettings, {CIO::iNone, 0})
SETTING (iDoorDrv, NotFixed, TInputSettings, {CIO::iRedBlack, CIO::ActiveGND}) // дверь водитель
SETTING (iDoorFP, NotFixed, TInputSettings, {CIO::iRedBlack, CIO::ActiveGND}) // дверь переднего пассажира
SETTING (iDoorRL, NotFixed, TInputSettings, {CIO::iRedBlack, CIO::ActiveGND}) // дверь задняя левая
SETTING (iDoorRR, NotFixed, TInputSettings, {CIO::iRedBlack, CIO::ActiveGND}) // дверь задняя правая
SETTING (iTrunk, NotFixed, TInputSettings, {CIO::iGreyBlack, CIO::ActiveGND}) // багажник
SETTING (iHood, NotFixed, TInputSettings, {CIO::iBrownBlack, CIO::ActiveGND}) // капот
SETTING (iIgn, NotFixed, TInputSettings, {CIO::iGreen, 0}) // Зажигание
SETTING (iHBrake, NotFixed, TInputSettings, {CIO::iLBlueBlack, CIO::ActiveGND}) // ручник
SETTING (iLamp, NotFixed, TInputSettings, {CIO::iNone, 0}) // Головное освещение (фары)
SETTING (iPark, NotFixed, TInputSettings, {CIO::iLBlueBlack, CIO::ActiveGND}) // положение ПАРК
SETTING (iBrake, NotFixed, TInputSettings, {CIO::iBlackWhite, 0}) // педаль тормоза
SETTING (iLeftTurnLight, NotFixed, TInputSettings, {CIO::iNone, 0}) // Включен левый сигнал поворота
SETTING (iRightTurnLight, NotFixed, TInputSettings, {CIO::iNone, 0}) // Включен правый сигнал поворота
SETTING (iArm, NotFixed, TInputSettings, {CIO::iNone, 0}) // для подключения внешнего GSM модуля, например
SETTING (iSensorAlarm, NotFixed, TInputSettings, {CIO::iNone, 0}) // зона тревоги с внешнего Сенсора (MWS или SHOCK)
SETTING (iSensorNotify, NotFixed, TInputSettings, {CIO::iNone, 0}) // зона предупреждения с внешнего Сенсора (MWS или SHOCK)
SETTING (iEngine, NotFixed, TInputSettings, {CIO::iNone, 0}) // двигатель работает
SETTING (iLock, NotFixed, TInputSettings, {CIO::iNone, 0}) // ЦЗ заперт
SETTING (iPreHeater, NotFixed, TInputSettings, {CIO::iNone, 0}) // подогреватель
SETTING (iLowFuelLevel, NotFixed, TInputSettings, {CIO::iNone, 0}) // Датчик низкого уровня топлива
SETTING (iACC, NotFixed, TInputSettings, {CIO::iNone, 0}) // аксессуары
SETTING (iKeyIn, NotFixed, TInputSettings, {CIO::iNone, 0}) // ключ в замке (не нужен!?)
SETTING (iSpark, NotFixed, TInputSettings, {CIO::iNone, 0}) // свечи накаливания дизеля
SETTING (iDoorsLamp, NotFixed, TInputSettings, {CIO::iNone, 0}) // Плафон освещения салона
SETTING (iTrunkLamp, NotFixed, TInputSettings, {CIO::iNone, 0}) // Плафон освещения багажника
SETTING (iTrunkWindow, NotFixed, TInputSettings, {CIO::iNone, 0}) // Концевик окна багажника
SETTING (iStartStop, NotFixed, TInputSettings, {CIO::iNone, 0}) // Вход Старт/Стоп от GSM модуля, например
SETTING (iNeutral, NotFixed, TInputSettings, {CIO::iNone, 0}) // Состояние нейтрали (для РКПП)
SETTING (iLauncher, NotFixed, TInputSettings, {CIO::iNone, 0}) // Состояние внешнего/стороннего модуля Запуска
SETTING (iDisarm, NotFixed, TInputSettings, {CIO::iNone, 0}) // для подключения внешнего GSM модуля, например
SETTING (iUnTrunk, NotFixed, TInputSettings, {CIO::iNone, 0}) // уведомление об отпирании багажника
SETTING (iUnLock, NotFixed, TInputSettings, {CIO::iNone, 0}) // ЦЗ отперт
#ifndef iFIRST
#define iFIRST iDevice1
#endif
SETTING_ALIAS(iLAST)
SETTING_ALIAS(iOFFSET = iFIRST)
SETTING_ALIAS(iCOUNT = (iLAST-iFIRST))
// дырка 75..93
SETTING_RSRV(ReservedInp = 93)
#if defined MOBICAR_3 || defined MAGICAR_X
SETTING (oWirePolarity, NotFixed, uint32_t, 0) // битовая маска: положительная полярность выходных проводов
SETTING (iTaho, NotFixed, TInputSettings, {CIO::iBlackPink, 0}) // мультиплексор для сигнала тахометра
#else
SETTING_RSRV(oWirePolarity)
SETTING (iTaho, NotFixed, TInputSettings, {CIO::iNone, 0}) // мультиплексор для сигнала тахометра
#endif
// настройки выходов - 96..159
// Неопределенные устройства
SETTING (oDevice1, NotFixed, uint32_t, 0)
SETTING (oDevice2, NotFixed, uint32_t, 0)
SETTING (oDevice3, NotFixed, uint32_t, 0)
SETTING (oDevice4, NotFixed, uint32_t, 0)
SETTING (oDevice5, NotFixed, uint32_t, 0)
SETTING (oDevice6, NotFixed, uint32_t, 0)
SETTING (oDevice7, NotFixed, uint32_t, 0)
SETTING (oDevice8, NotFixed, uint32_t, 0)
#if defined MOBICAR_1_2
// Базовые устройства Охранной системы
SETTING (oSiren, NotFixed, uint32_t, oBIT(oBrown)) // Сирена
SETTING (oHorn, NotFixed, uint32_t, 0) // Клаксон
SETTING (oLights, NotFixed, uint32_t, oBIT(oVioletYellow)|oBIT(oVioletBrown))// Поворотники
SETTING (oLamp, NotFixed, uint32_t, 0) // Головное освещение или габариты
SETTING (oPassiveBlockage, NotFixed, uint32_t, 0) // Пассивная блокировка (когда выключена, цепь разомкнута, блокировка включена)
SETTING (oActiveBlockage, NotFixed, uint32_t, oBIT(oBlue)) // Активная блокировка (когда выключена, цепь замкнута, блокировка выключена)
SETTING (oLockDoors, NotFixed, uint32_t, oBIT(oGreen)) // Запереть все двери
SETTING (oUnlockDoors, NotFixed, uint32_t, oBIT(oYellow)) // Отпереть все двери
SETTING (oUnlockDoorDrv, NotFixed, uint32_t, 0) // Отпереть дверь водителя
SETTING (oLockTrunk, NotFixed, uint32_t, 0) // Запереть багажник
SETTING (oUnlockTrunk, NotFixed, uint32_t, 0) // Отпереть багажник
SETTING (oLockHood, NotFixed, uint32_t, 0) // Запереть Капот
SETTING (oUnLockHood, NotFixed, uint32_t, 0) // Отпереть капот
SETTING (oCloseWindows, NotFixed, uint32_t, 0) // Закрыть окна
SETTING (oPreHeaterOn, NotFixed, uint32_t, 0) // Включение предпускового подогревателя
SETTING (oPreHeaterOff, NotFixed, uint32_t, 0) // Выключение предпускового подогревателя
SETTING (oImmOn, NotFixed, uint32_t, 0) // Устройство включающее Иммобилайзер
SETTING (oImmOff, NotFixed, uint32_t, 0) // Устройство выключающее Иммобилайзер
SETTING (oService, NotFixed, uint32_t, 0) // Устройство переводящее автомобиль в Сервисный режим
SETTING (oDisarm, NotFixed, uint32_t, 0) // Устройство осуществляющее снятие с Охраны (можно использовать как выход статической блокировки)
SETTING (oArm, NotFixed, uint32_t, 0) // Устройство осуществляющее постановку под Охрану (можно использовать как выход статической блокировки)
SETTING (oAlarm, NotFixed, uint32_t, 0) // Устройство осуществляющее включение тревоги (можно использовать как выход статической блокировки)
SETTING (oAutoStart, NotFixed, uint32_t, 0) // Состояние Автозапуска
// Базовые устройства АвтоЗапуска (подменяют или имитируют присутствие водителя в автомобиле)
SETTING (oDoorWag, NotFixed, uint32_t, 0) // Устройство махающее дверью
SETTING (oIgn, NotFixed, uint32_t, oBIT(oBrownGreen)) // Включение зажигания
SETTING (oBrake, NotFixed, uint32_t, 0) // Педаль тормоза
SETTING (oKeyIn, NotFixed, uint32_t, 0) // Ключ в замке
SETTING (oAcc, NotFixed, uint32_t, oBIT(oBrownWhite)) // Аксессуары
SETTING (oBrakeControl, Fixed, uint32_t, 0) // не используется. Делать "дырку" нельзя, ломается индексация массива
SETTING (oAuxBrake, NotFixed, uint32_t, 0) // Дополнительная линия педали тормоза
SETTING (oAuxIgn, NotFixed, uint32_t, oBIT(oBrownViolet)) // Дополнительная линия зажигания
SETTING (oSSButton, NotFixed, uint32_t, 0) // Кнопка Старт/Стоп
SETTING (oImmBypass, NotFixed, uint32_t, 0) // Обходчик встроенного иммобилайзера
SETTING (oCrank, NotFixed, uint32_t, oBIT(oBrownYellow)) // Стартер
SETTING (oCrankDisable, NotFixed, uint32_t, 0) // Блокировка Стартера
// Дополнительные
SETTING (oLockIgn, NotFixed, uint32_t, 0) // Блокировка зажигания (когда включена, зажигание заблокировано)
SETTING (oUnLockIgn, NotFixed, uint32_t, 0) // Разблокировка зажигания (когда включена, зажигание разблокировано)
SETTING (oKLine1Relay, NotFixed, uint32_t, 0) // Устройство коммутирующее KLine интерфейс
SETTING (oAux1, NotFixed, uint32_t, 0) // Доп.канал #1
SETTING (oAux2, NotFixed, uint32_t, 0) // Доп.канал #2
SETTING (oAux3, NotFixed, uint32_t, 0) // Доп.канал #3
SETTING (oEmergencyBraking, NotFixed, uint32_t, 0) // Выход сигнала Экстренного торможения
SETTING (oIllumination, NotFixed, uint32_t, 0) // Выход для сигналов вежливой подсветки
SETTING (oFoldMirrors, NotFixed, uint32_t, 0) // Сложить зеркала
SETTING (oUnfoldMirrors, NotFixed, uint32_t, 0) // Разложить зеркала
SETTING (oCloseSunroof, NotFixed, uint32_t, 0) // Закрыть люк
SETTING (oMoveSunroof, NotFixed, uint32_t, 0) // Сдвинуть люк
SETTING (oHeatedSeats, NotFixed, uint32_t, 0) // Обогрев сидений
SETTING (oTriggerDoors, NotFixed, uint32_t, 0) // Триггерное управление замками дверей
SETTING (oIgnSupport, NotFixed, uint32_t, 0) // Состояние поддержки зажигания
SETTING (oArmWithoutTag, NotFixed, uint32_t, 0) // Состояние "Охрана без метки"
SETTING (oHeatedWindows, NotFixed, uint32_t, 0) // Обогрев окон
SETTING (oKLine2Relay, Fixed, uint32_t, 0) // Mobicar3: Устройство коммутирующее KLine интерфейс
SETTING (oDVR, NotFixed, uint32_t, 0) // Выход на видеорегистратор
#elif defined MOBICAR_3 || defined MAGICAR_X
// Базовые устройства Охранной системы
SETTING (oSiren, NotFixed, uint32_t, oBIT(oBrown)) // Сирена
SETTING (oHorn, NotFixed, uint32_t, 0) // Клаксон
SETTING (oLights, NotFixed, uint32_t, oBIT(oBrownViolet)|oBIT(oBrownWhite))// Поворотники
SETTING (oLamp, NotFixed, uint32_t, 0) // Головное освещение или габариты
SETTING (oPassiveBlockage, NotFixed, uint32_t, 0) // Пассивная блокировка (когда выключена, цепь разомкнута, блокировка включена)
SETTING (oActiveBlockage, NotFixed, uint32_t, oBIT(oBlue)) // Активная блокировка (когда выключена, цепь замкнута, блокировка выключена)
SETTING (oLockDoors, NotFixed, uint32_t, oBIT(oBrownGreen)) // Запереть все двери
SETTING (oUnlockDoors, NotFixed, uint32_t, oBIT(oBrownYellow)) // Отпереть все двери
SETTING (oUnlockDoorDrv, NotFixed, uint32_t, 0) // Отпереть дверь водителя
SETTING (oLockTrunk, NotFixed, uint32_t, 0) // Запереть багажник
SETTING (oUnlockTrunk, NotFixed, uint32_t, 0) // Отпереть багажник
SETTING (oLockHood, NotFixed, uint32_t, 0) // Запереть Капот
SETTING (oUnLockHood, NotFixed, uint32_t, 0) // Отпереть капот
SETTING (oCloseWindows, NotFixed, uint32_t, 0) // Закрыть окна
SETTING (oPreHeaterOn, NotFixed, uint32_t, 0) // Включение предпускового подогревателя
SETTING (oPreHeaterOff, NotFixed, uint32_t, 0) // Выключение предпускового подогревателя
SETTING (oImmOn, NotFixed, uint32_t, 0) // Устройство включающее Иммобилайзер
SETTING (oImmOff, NotFixed, uint32_t, 0) // Устройство выключающее Иммобилайзер
SETTING (oService, NotFixed, uint32_t, 0) // Устройство переводящее автомобиль в Сервисный режим
SETTING (oDisarm, NotFixed, uint32_t, 0) // Устройство осуществляющее снятие с Охраны (можно использовать как выход статической блокировки)
SETTING (oArm, NotFixed, uint32_t, 0) // Устройство осуществляющее постановку под Охрану (можно использовать как выход статической блокировки)
SETTING (oAlarm, NotFixed, uint32_t, 0) // Устройство осуществляющее включение тревоги (можно использовать как выход статической блокировки)
SETTING (oAutoStart, NotFixed, uint32_t, 0) // Состояние Автозапуска
// Базовые устройства АвтоЗапуска (подменяют или имитируют присутствие водителя в автомобиле)
SETTING (oDoorWag, NotFixed, uint32_t, 0) // Устройство махающее дверью
SETTING (oIgn, NotFixed, uint32_t, oBIT(oGreenRelay)) // Включение зажигания
SETTING (oBrake, NotFixed, uint32_t, 0) // Педаль тормоза
SETTING (oKeyIn, NotFixed, uint32_t, 0) // Ключ в замке
SETTING (oAcc, NotFixed, uint32_t, oBIT(oWhiteRelay)) // Аксессуары
SETTING (oBrakeControl, Fixed, uint32_t, 0) // не используется. Выкидывать нельзя, ломается адресация выходов как массива
SETTING (oAuxBrake, NotFixed, uint32_t, 0) // Дополнительная линия педали тормоза
SETTING (oAuxIgn, NotFixed, uint32_t, 0) // Дополнительная линия зажигания
SETTING (oSSButton, NotFixed, uint32_t, 0) // Кнопка Старт/Стоп
SETTING (oImmBypass, NotFixed, uint32_t, 0) // Обходчик встроенного иммобилайзера
SETTING (oCrank, NotFixed, uint32_t, oBIT(oYellowRelay)) // Стартер
SETTING (oCrankDisable, NotFixed, uint32_t, 0) // Блокировка Стартера
// Дополнительные
SETTING (oLockIgn, NotFixed, uint32_t, 0) // Блокировка зажигания (когда включена, зажигание заблокировано)
SETTING (oUnLockIgn, NotFixed, uint32_t, 0) // Разблокировка зажигания (когда включена, зажигание разблокировано)
SETTING (oKLine1Relay, NotFixed, uint32_t, oBIT(oOrangeBreak)) // Устройство коммутирующее KLine интерфейс
SETTING (oAux1, NotFixed, uint32_t, 0) // Доп.канал #1
SETTING (oAux2, NotFixed, uint32_t, 0) // Доп.канал #2
SETTING (oAux3, NotFixed, uint32_t, 0) // Доп.канал #3
SETTING (oEmergencyBraking, NotFixed, uint32_t, 0) // Выход сигнала Экстренного торможения
SETTING (oIllumination, NotFixed, uint32_t, 0) // Выход для сигналов вежливой подсветки
SETTING (oFoldMirrors, NotFixed, uint32_t, 0) // Сложить зеркала
SETTING (oUnfoldMirrors, NotFixed, uint32_t, 0) // Разложить зеркала
SETTING (oCloseSunroof, NotFixed, uint32_t, 0) // Закрыть люк
SETTING (oMoveSunroof, NotFixed, uint32_t, 0) // Сдвинуть люк
SETTING (oHeatedSeats, NotFixed, uint32_t, 0) // Обогрев сидений
SETTING (oTriggerDoors, NotFixed, uint32_t, 0) // Триггерное управление замками дверей
SETTING (oIgnSupport, NotFixed, uint32_t, 0) // Состояние поддержки зажигания
SETTING (oArmWithoutTag, NotFixed, uint32_t, 0) // Состояние "Охрана без метки"
SETTING (oHeatedWindows, NotFixed, uint32_t, 0) // Обогрев окон
SETTING (oKLine2Relay, NotFixed, uint32_t, oBIT(oPinkBreak)) // Mobicar3: Устройство коммутирующее KLine интерфейс
SETTING (oDVR, NotFixed, uint32_t, 0) // Выход на видеорегистратор
//SETTING (oTriggerLights, NotFixed, uint32_t, 0) // Выход на триггерную кнопку включения аварийки
#endif // outputs
#ifndef oFIRST
#define oFIRST oDevice1
#endif
SETTING_ALIAS(oLAST)
SETTING_ALIAS(oOFFSET = oFIRST)
SETTING_ALIAS(oCOUNT = (oLAST-oFIRST))
SETTING_RSRV(ReservedOutput = 159)
// Общий принцип настройки последовательностей:
// Если выход один, либо существует возможность соединить два выхода параллельно, то
// активное значение последовательности должно быть немного (на 10-50мс) задержано по времени
// по отношению к моменту включения пассивного состояния на противоположенной последовательности.
// Например, если у последовательности выключения выхода пассивное состояние наступает через 100мс,
// то активное состояние у последовательности включения должно быть задержано на 110-150мс от начала.
// Еще одно замечание.
// Существуют устройства, которые сами могут отключаться, например, "Замки"/"Зеркала"/"Люк"/"Багажник",
// соответственно их можно только закрыть или открыть.
// А существуют устройства, которые включаются/выключаются по команде.. такие устройства, как правило,
// с бесконечным временем работы, например, "Подогрев сидений"/"Аварийка"/"Фары" и т.п., соответственно их
// можно включить или выключить.
// Соответственно, для устройств, которые могут быть включены/выключены, используются двойные/комплементарные
// импульсные последовательности.
// настройки последовательностей: 160..299
SETTING (seqSirenArm, NotFixed, TSequence, {qMS( 10),5}) // Сирена: Постановка под Охрану
SETTING (seqSirenDisarm, NotFixed, TSequence, {qMS( 10),5,10,5}) // Сирена: Снятие с Охраны
SETTING (seqSirenAlarm, NotFixed, TSequence, {qMS(100),0xF0}) // Сирена: Тревога
SETTING (seqSirenWarning, NotFixed, TSequence, {qMS( 10),0xF2,10,5,10,5,10,5}) // Сирена: Внимание!
SETTING (seqSirenCaution, NotFixed, TSequence, {qMS( 10),5,5,5}) // Сирена: Предупреждение
SETTING (seqSirenNotify, NotFixed, TSequence, {qMS( 10),5}) // Сирена: Извещение
SETTING (seqSirenShockNotify, NotFixed, TSequence, {qMS( 10),0xF2,5,5,5,5,5,5}) // Сирена: Предупреждение по датчику Удара
SETTING (seqSirenService, NotFixed, TSequence, {qMS( 10),0xF2,10,5,10,5,10,5}) // Сирена: Сервисный режим
SETTING (seqSirenDisarmAfterAlarm, NotFixed, TSequence, {qMS( 10),0xF2,10,5,10,5,10,5,10,5})// Сирена: Снятие с Охраны после тревоги
SETTING (seqSirenImHere, NotFixed, TSequence, {qMS( 50),0xF2,4,4,4,4,4,4,4,4,128,0xF3})// Сирена: Поиск автомобиля на парковке
SETTING (seqSirenReserved2, NotFixed, TSequence, {qMS( 0)}) // Сирена: Резерв
SETTING (seqHornArm, NotFixed, TSequence, {qMS( 10),3}) // Клаксон: Постановка под Охрану
SETTING (seqHornDisarm, NotFixed, TSequence, {qMS( 10),3,10,3}) // Клаксон: Снятие с Охраны
SETTING (seqHornAlarm, NotFixed, TSequence, {qMS( 10),5,10,0xF1}) // Клаксон: Тревога
SETTING (seqHornWarning, NotFixed, TSequence, {qMS( 10),0xF2,10,3,10,3,10,3}) // Клаксон: Внимание!
SETTING (seqHornCaution, NotFixed, TSequence, {qMS( 10),3,5,3}) // Клаксон: Предупреждение
SETTING (seqHornNotify, NotFixed, TSequence, {qMS( 10),3}) // Клаксон: Извещение
SETTING (seqHornShockNotify, NotFixed, TSequence, {qMS( 10),0xF2,5,3,5,3,5,3}) // Клаксон: Предупреждение по датчику Удара
SETTING (seqHornService, NotFixed, TSequence, {qMS( 10),0xF2,10,3,10,3,10,3}) // Клаксон: Сервисный режим
SETTING (seqHornDisarmAfterAlarm, NotFixed, TSequence, {qMS( 10),0xF2,10,5,10,5,10,5,10,5})// Клаксон: Снятие с Охраны после тревоги
SETTING (seqHornImHere, NotFixed, TSequence, {qMS( 50),0xF2,4,1,4,1,4,1,4,1,128,0xF3})// Клаксон: Поиск автомобиля на парковке
SETTING (seqHornReserved2, NotFixed, TSequence, {qMS( 0)}) // Клаксон: Резерв
SETTING (seqLightsArm, NotFixed, TSequence, {qMS(100),5}) // Поворотники: Постановка под Охрану
SETTING (seqLightsDisarm, NotFixed, TSequence, {qMS(100),5,5,5}) // Поворотники: Снятие с Охраны
SETTING (seqLightsAlarm, NotFixed, TSequence, {qMS(100),5,5,0xF1}) // Поворотники: Тревога
SETTING (seqLightsWarning, NotFixed, TSequence, {qMS(100),0xF2,2,5,5,5,5,5}) // Поворотники: Внимание!
SETTING (seqLightsCaution, NotFixed, TSequence, {qMS(100),2,2,2}) // Поворотники: Предупреждение
SETTING (seqLightsNotify, NotFixed, TSequence, {qMS(100),2}) // Поворотники: Извещение
SETTING (seqLightsShockNotify, NotFixed, TSequence, {qMS(100),3}) // Поворотники: Предупреждение по датчику Удара
SETTING (seqLightsService, NotFixed, TSequence, {qMS(100),0xF2,2,5,5,5,5,5}) // Поворотники: Сервисный режим
SETTING (seqLightsDisarmAfterAlarm, NotFixed, TSequence, {qMS(100),0xF2,2,5,5,5,5,5,5,5})// Поворотники: Снятие с Охраны после тревоги
SETTING (seqLightsImHere, NotFixed, TSequence, {qMS(100),0xF2,2,5,5,0xF3}) // Поворотники: Поиск автомобиля на парковке
SETTING (seqLightsAutoStartMode, NotFixed, TSequence, {qMS(100),0xF2,10,5,30,0xF3}) // Поворотники: Режим AutoStart
SETTING (seqLightsAutoStartOnOff, NotFixed, TSequence, {qMS(100),14}) // Поворотники: Включение/выключение режима AutoStart
SETTING (seqLampArm, NotFixed, TSequence, {qMS(100),5}) // Фары/габариты: Постановка под Охрану
SETTING (seqLampDisarm, NotFixed, TSequence, {qMS(100),5,5,5}) // Фары/габариты: Снятие с Охраны
SETTING (seqLampAlarm, NotFixed, TSequence, {qMS(100),5,5,0xF1}) // Фары/габариты: Тревога
SETTING (seqLampWarning, NotFixed, TSequence, {qMS(100),0xF2,2,5,5,5,5,5}) // Фары/габариты: Внимание!
SETTING (seqLampCaution, NotFixed, TSequence, {qMS(100),2,2,2}) // Фары/габариты: Предупреждение
SETTING (seqLampNotify, NotFixed, TSequence, {qMS(100),2}) // Фары/габариты: Извещение
SETTING (seqLampShockNotify, NotFixed, TSequence, {qMS(100),3}) // Фары/габариты: Предупреждение по датчику Удара
SETTING (seqLampService, NotFixed, TSequence, {qMS(100),0xF2,2,5,5,5,5,5}) // Фары/габариты: Сервисный режим
SETTING (seqLampDisarmAfterAlarm, NotFixed, TSequence, {qMS(100),0xF2,2,5,5,5,5,5,5,5})// Фары/габариты: Снятие с Охраны после тревоги
SETTING (seqLampImHere, NotFixed, TSequence, {qMS(100),0xF2,2,5,5,0xF3}) // Фары/габариты: Поиск автомобиля на парковке
SETTING (seqLampAutoStartMode, NotFixed, TSequence, {qMS(100),0xF2,10,5,30,0xF3}) // Фары/габариты: Режим AutoStart
SETTING (seqLampAutoStartOnOff, NotFixed, TSequence, {qMS(100),14}) // Фары/габариты: Включение/выключение режима AutoStart
SETTING (seqActiveBlockageOn, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Включить активную блокировку
SETTING (seqActiveBlockageOff, NotFixed, TSequence, {qMS( 10),0}) // Выключить активную блокировку
SETTING (seqPassiveBlockageOn, NotFixed, TSequence, {qMS( 10),0}) // Включить пассивную блокировку
SETTING (seqPassiveBlockageOff, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Выключить пассивную блокировку
SETTING (seqLockDoors, NotFixed, TSequence, {qMS( 10),0xF2,1,50}) // Запереть центральный замок (периметр/двери)
SETTING (seqUnlockDoors, NotFixed, TSequence, {qMS( 10),0xF2,1,50}) // Отпереть центральный замок
SETTING (seqUnlockDoorDrv, NotFixed, TSequence, {qMS( 10),0xF2,1,50}) // Отпереть только дверь водителя
SETTING (seqLockHood, NotFixed, TSequence, {qMS( 10),0xF2,1,80}) // Запереть капот
SETTING (seqUnlockHood, NotFixed, TSequence, {qMS( 10),0xF2,1,80}) // Отпереть капот
SETTING (seqUnlockHoodService, NotFixed, TSequence, {qMS(100),0xF2,25,8}) // Отпереть капот в режиме Автосервис
SETTING (seqLockTrunk, NotFixed, TSequence, {qMS( 10),0xF2,1,50}) // Запереть багажник
SETTING (seqUnlockTrunk, NotFixed, TSequence, {qMS( 10),0xF2,1,50}) // Отпереть багажник
SETTING (seqCloseWindows, NotFixed, TSequence, {qMS(100),200}) // Закрыть окна
SETTING (seqPreHeaterOn, NotFixed, TSequence, {qMS(100),0xF2,1,0xF0}) // Включить предпусковой подогреватель <oPreHeaterOn>
SETTING (seqPreHeaterOff, NotFixed, TSequence, {qMS(100),0xF2,1,10}) // Выключить предпусковой подогреватель <oPreHeaterOff>
SETTING (seqUnused1, NotFixed, TSequence, {qMS( 0)}) // Неиспользуется
SETTING (seqUnused2, NotFixed, TSequence, {qMS( 0)}) // Неиспользуется
SETTING (seqUnused3, NotFixed, TSequence, {qMS( 0)}) // Неиспользуется
SETTING (seqUnused4, NotFixed, TSequence, {qMS( 0)}) // Неиспользуется
SETTING (seqImmOn, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Включить Иммобилайзер <oImmOn>
SETTING (seqImmOff, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Выключить Иммобилайзер <oImmOff>
SETTING (seqServiceOn, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Включение <oService>
SETTING (seqServiceOff, NotFixed, TSequence, {qMS( 10),0}) // Выключение <oService>
SETTING (seqDisarmOn, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Включение <oDisarm>
SETTING (seqDisarmOff, NotFixed, TSequence, {qMS( 10),0}) // Выключение <oDisarm>
SETTING (seqArmOn, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Включение Охраны <oArm>
SETTING (seqArmOff, NotFixed, TSequence, {qMS( 10),0}) // Выключение Охраны <oArm>
SETTING (seqAlarmOn, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Включение Тревоги <oAlarm>
SETTING (seqAlarmOff, NotFixed, TSequence, {qMS( 10),0}) // Выключение Тревоги <oAlarm>
SETTING (seqAutoStartOn, NotFixed, TSequence, {qMS(100),0}) // Включение Автозапуска <oAutoStart>
SETTING (seqAutoStartDone, NotFixed, TSequence, {qMS(100),0}) // Успешный пуск Автозапуска <oAutoStart>
SETTING (seqAutoStartOff, NotFixed, TSequence, {qMS(100),0}) // Выключение Автозапуска <oAutoStart>
SETTING (seqLockIgnOn, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Включить блокировку зажигания <oLockIgn>
SETTING (seqLockIgnOff, NotFixed, TSequence, {qMS( 10),0}) // Выключить блокировку зажигания <oLockIgn>
SETTING (seqUnLockIgnOn, NotFixed, TSequence, {qMS( 10),0xF2,1,0xF0}) // Включить разблокировку зажигания <oUnLockIgn>
SETTING (seqUnLockIgnOff, NotFixed, TSequence, {qMS( 10),0}) // Выключить разблокировку зажигания <oUnLockIgn>
SETTING (seqAux1, NotFixed, TSequence, {qMS(100),5}) // Сигнал включения Доп.канала #1 <oAux1>
SETTING (seqAux2, NotFixed, TSequence, {qMS(100),5}) // Сигнал включения Доп.канала #2 <oAux2>
SETTING (seqAux3, NotFixed, TSequence, {qMS(100),5}) // Сигнал включения Доп.канала #3 <oAux3>
// Последовательности для модуля Запуска
SETTING (seqDoorWag, NotFixed, TSequence, {qMS(100),0xF2,5,5,5}) // Махнуть дверью: пауза для некоторых тормозных НИССАНов (Демин/Семибратов просили добавить)
SETTING (seqImmByOff, NotFixed, TSequence, {qMS(100),6}) // Обходчик иммобилайзера: выключить
SETTING (seqImmByOn, NotFixed, TSequence, {qMS(100),0xF2,1,0xF0}) // Обходчик иммобилайзера: включить
SETTING (seqKeyInOff, NotFixed, TSequence, {qMS(100),5}) // Ключ в замке: выключить
SETTING (seqKeyInOn, NotFixed, TSequence, {qMS(100),0xF2,2,0xF0}) // Ключ в замке: включить
SETTING (seqAccOff, NotFixed, TSequence, {qMS(100),4}) // Аксессуары: выключить
SETTING (seqAccOn, NotFixed, TSequence, {qMS(100),0xF2,3,0xF0}) // Аксессуары: включить
SETTING (seqIgnOff, NotFixed, TSequence, {qMS(100),3}) // Зажигание 1: выключить
SETTING (seqIgnOn, NotFixed, TSequence, {qMS(100),0xF2,5,0xF0}) // Зажигание 1: включить
SETTING (seqBrakeOff, NotFixed, TSequence, {qMS(100),2}) // Педаль тормоза: выключить
SETTING (seqBrakeOn, NotFixed, TSequence, {qMS(100),0xF2,5,0xF0}) // Педаль тормоза: включить
SETTING (seqCrankOn, NotFixed, TSequence, {qMS(100),0xF2,10,30}) // Стартер: включить
SETTING (seqCrankDisableOff, NotFixed, TSequence, {qMS(100),7}) // Блокировка стартера: выключить
SETTING (seqCrankDisableOn, NotFixed, TSequence, {qMS(100),0xF0}) // Блокировка стартера: включить
SETTING (seqAuxIgnOff, NotFixed, TSequence, {qMS(100),3}) // Зажигание 2: выключить
SETTING (seqAuxIgnOn, NotFixed, TSequence, {qMS(100),0xF2,5,0xF0}) // Зажигание 2: включить
SETTING (seqAuxBrakeOff, NotFixed, TSequence, {qMS(100),1}) // Педаль тормоза 2: выключить
SETTING (seqAuxBrakeOn, NotFixed, TSequence, {qMS(100),0xF2,6,0xF0}) // Педаль тормоза 2: включить
SETTING (seqPrestartSSB, NotFixed, TSequence, {qMS(100),0xF2,10,6}) // Первое нажатие на SSB в SetPRESTART
SETTING (seqCrankSSB, NotFixed, TSequence, {qMS(100),0xF2,10,30}) // Нажатие на SSB во время CRANK
SETTING (seqStopSSB, NotFixed, TSequence, {qMS(100),0xF2,21,6}) // Первое нажатие на SSB в SetSTOP, при неавтоматическом подборе нажатий! (пауза в начале для учета параллельных процессов связанных с окончанием, например, включение/выключение обходчика и др.)
SETTING (seqPressSSB, NotFixed, TSequence, {qMS(100),0xF2,10,6}) // Сигнал дополнительных/повторных нажатий на SSB (PRESTART/STOP)
SETTING (seqEmergencyBraking, NotFixed, TSequence, {qMS(100),0xF2,5,5,0xF2}) // Сигнал экстренного торможения
SETTING (seqIllumination, NotFixed, TSequence, {qMS(100),20,0xF3,10,0xF5,20,0xF7,20,0xF9,20,0xFB,20,0xFD,20,0xFF,20})// Сигнал вежливой подсветки
SETTING (seqFoldMirrors, NotFixed, TSequence, {qMS(100),0}) // Сложить зеркала
SETTING (seqUnfoldMirrors, NotFixed, TSequence, {qMS(100),0}) // Разложить зеркала
SETTING (seqCloseSunroof, NotFixed, TSequence, {qMS(100),0}) // Закрыть люк
SETTING (seqMoveSunroof, NotFixed, TSequence, {qMS(100),0}) // Сдвинуть люк
SETTING (seqShockAlarmTestMode, NotFixed, TSequence, {qMS( 10),0xF2,5,50}) // Сигнал тревоги по датчику удара в режиме настройки
SETTING (seqHeatedSeatsOn, NotFixed, TSequence, {qMS(100),0}) // Включение подогрева сидений
SETTING (seqHeatedSeatsOff, NotFixed, TSequence, {qMS(100),0}) // Выключение подогрева сидений
SETTING (seqIgnSupportOn, NotFixed, TSequence, {qMS(100),0xF0}) // Статус включение поддержки зажигания
SETTING (seqIgnSupportOff, NotFixed, TSequence, {qMS(100),0}) // Статус выключение поддержки зажигания
SETTING (seqArmWithoutTagOn, NotFixed, TSequence, {qMS(100),0xF2,10,0xF0}) // Включение состояния "Охрана без метки"
SETTING (seqArmWithoutTagOff, NotFixed, TSequence, {qMS(100),0}) // Выключение состояния "Охрана без метки"
SETTING (seqHeatedWindowsOn, NotFixed, TSequence, {qMS(100),0}) // Включение подогрева окон
SETTING (seqHeatedWindowsOff, NotFixed, TSequence, {qMS(100),0}) // Выключение подогрева окон
//SETTING (seqTriggerStart, NotFixed, TSequence, {qMS(100),30}) // Сигнал первого нажатия на триггерную кнопку
//SETTING (seqTriggerNext, NotFixed, TSequence, {qMS( 10),10,10}) // Сигнал всех последующих нажатий на триггерную кнопку
#ifndef seqFIRST // последовательности ядра
#define seqFIRST seqSirenArm
#endif
SETTING_ALIAS(seqHOLE)
SETTING_RSRV(seqProgs = 283)
// Шаблоны CAN прошивки (обезличиненные, приобретают смысл в CAN прошивке)
// В Universe, доп. импульсные последовательности используются максимум 4ре штуки...
// Поэтому, при нехватке последователльностей, можно "откусывать" от программируемых.
SETTING (seqProg16, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg15, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg14, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg13, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg12, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg11, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg10, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg9, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg8, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg7, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg6, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg5, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg4, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg3, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg2, NotFixed, TSequence, {qMS( 0)})
SETTING (seqProg1, NotFixed, TSequence, {qMS( 0)})
SETTING_ALIAS(seqOFFSET = seqFIRST)
SETTING_ALIAS(seqCOUNT = (seqProg1+1-seqFIRST))
SETTING_RSRV(seqLAST = 299)
// прочие системные настройки: 300
SETTING (KeyAES, NotFixed, TKeyAES, {0}) // ключ шифрования
SETTING (Kxx, NotFixed, uint16_t, 37) // ~690RPM // Калибровочный коэф. холостого хода
SETTING (VIN, NotFixed, TVehicleID, {0}) // VIN-код авто
SETTING (ImmoKeyArr, NotFixed, TImmoKey, {0}) // Ключ обходчика иммобилайзера
SETTING_RSRV(BrelokCount) // Количество подшитых брелков X1/X2
SETTING (ImmoKeyAuxArr, NotFixed, TImmoKey, {0}) // Расширение ключа обходчика иммобилайзера (дополнительное поле)
SETTING_RSRV(LastSystemSettings = 0x013F) // 319
// настройки индикации светом: 0x0140 (320)
SETTING (LightsArm, NotFixed, bit_t, 1) // при включении охраны
SETTING (LightsDisarm, NotFixed, bit_t, 1) // при выключении охраны
SETTING (LightsAlarm, NotFixed, bit_t, 1) // при тревоге
SETTING (LightsTrunkLock, NotFixed, bit_t, 0) // при запирании багажника
SETTING (LightsAutoStartMode, NotFixed, uint8_t, defLightsAutoStartMode) // режим работы световой индикации при автозапуске: 0=OFF; 1=при вкл/выкл Автозапуска; 2=..и во время Автозапуска
SETTING_RSRV(AutoStartLightsAlwaysOn) // при работе автозапуска
SETTING_RSRV(LightsAutoStartOff) // при выключении автозапуска
SETTING_RSRV(LightsAuxChannelOn) // при включении дополнительного канала
SETTING (IlluminationMode, NotFixed, uint8_t, defIlluminationMode) // режим включения вежливой подсветки: 0=OFF; 1=Arm; 2=Disarm; 3=Arm+Disarm.
SETTING_RSRV(IndLightIllumDuration) // вежливая подсветка, длительность
SETTING (LightsShockNotify, NotFixed, bit_t, 1) // при срабатывании предупреждения датчика удара
SETTING_RSRV(LightsSelfArming) // предупреждение об автопостановке
SETTING_RSRV(_EmergencyBraking) // выдавать сигнал об экстренном торможении
SETTING_RSRV(LightsHiJackOff) // при выходе из хайджека
SETTING_RSRV(LightsImmoOff) // при выходе из иммобилайзера
SETTING_RSRV(LightsNoReservation) // не выполнена подготовка к автозапуску
SETTING_RSRV(LightsHeadLampOn) // не выключены фары
SETTING_RSRV(IndLightReserved = 0x015F)
// настройки индикации сиреной: 0x0160 (352)
SETTING (SoundArm, NotFixed, bit_t, 1) // при включении охраны
SETTING (SoundDisarm, NotFixed, bit_t, 1) // при выключении охраны
SETTING (SoundsDisable, NotFixed, bit_t, 0) // отключение всех звуков: тревога/подтверждения
SETTING_RSRV(SoundAutoStartOn) // при включении автозапуска
SETTING_RSRV(SoundAutoStartMode) // при остатке времени автозапуска 2 минуты
SETTING_RSRV(SoundAutoStartOff) // при выключении автозапуска
SETTING_RSRV(SoundAuxChannelOn) // при включении дополнительного канала
SETTING_RSRV(SoundShockNotify) // при срабатывании предупреждения датчика удара
SETTING_RSRV(SoundHeadLampOn) // не выключены фары
SETTING_RSRV(SoundSelfArming) // предупреждение об автопостановке
SETTING_RSRV(SoundHiJackOff) // при выходе из режима хайджек
SETTING_RSRV(SoundServiceNotify) // напоминание о необходимости выйти из режима Автосервис
SETTING_RSRV(SoundImmoOff) // при выходе из режима иммобилайзера
SETTING_RSRV(SoundNoReservation) // не выполнена подготовка к автозапуску
SETTING (SoundsNoticesDisable, NotFixed, bit_t, 0) // Отключить все звуки уведомлений
SETTING_RSRV(SoundsReserved = 0x017F)
// настройки центрального замка: 0x0180 (384)
SETTING_RSRV(LockOnAutoArm) // запирание при автопостановке
SETTING_RSRV(LockOnArmReturn) // запирание при возврате в охрану
SETTING (LockByDriveMode, NotFixed, uint8_t, defLockByDriveMode) // режим запирания ЦЗ: нет / по педали тормоза / по началу движения / по включению зажигания
SETTING (LockOnAutostartBegin, NotFixed, bit_t, 0) // запирание при начале автозапуска
SETTING (LockOnAutostartEnd, NotFixed, bit_t, 0) // запирание по окончанию автозапуска
SETTING (LockOnAlarmEnd, NotFixed, bit_t, 0) // запирание при выходе из тревоги
SETTING (LockOnTrunkClose, NotFixed, bit_t, 0) // запирание по завершению процедуры открытия багажника в Охране
SETTING (UnlockByParkMode, NotFixed, uint8_t, defUnlockByParkMode)// отпирание при выключении зажигания
SETTING_RSRV(UnlockByEmergencyBraking) // отпирание при экстренном торможении
SETTING (UnlockPriority, NotFixed, bit_t, 0) // приоритетное отпирание замков
SETTING (DriveDoorsAutostart, NotFixed, bit_t, 0) // Управлять замками дверей по SlaveArm/SlaveDisarm в режиме Автозапуска
SETTING_RSRV(LockReserved = 0x019F)
// настройки режимов "охрана", "снято с охраны": 0x01A0 (416)
SETTING_RSRV(ArmAuto) // автопостановка при закрытии дверей, нет / по закрытию дверей / по отсутствию метки
SETTING_RSRV(ArmAutoTimeout) // таймаут автопостановки
SETTING (Comfort, NotFixed, uint8_t, 1) // управление функциями "комфорта": зеркала, стекла, люк
SETTING (ArmReturnTimeIndex, NotFixed, uint8_t, defArmReturnTimeIndex) // индекс массива времен автоматической перепостановки
SETTING (PlafondAlarmDelay, NotFixed, uint8_t, defPlafondAlarmDelay) // время блокировки тревог от сигналов освещения багажника и салона
SETTING (DoorsLampDeciseconds, NotFixed, uint8_t, defDoorsLampDeciseconds)// таймер отсрочки выключенного состояния плафона освещения салона
SETTING (TrunkLampDeciseconds, NotFixed, uint8_t, defTrunkLampDeciseconds)// таймер отсрочки выключенного состояния плафона освещения багажника
SETTING (HandsfreeMode, NotFixed, uint8_t, 0) // постановка/снятие при появлении телефона-метки: бит 0 - автопостановка, бит 1 - автоснятие
SETTING (DisarmWithTagOnly, NotFixed, bit_t, 0) // снятие с охраны только при наличии телефона-метки, прерывание тревоги не запрещает
SETTING (DriveBuiltinSystem, NotFixed, bit_t, 1) // управлять штатной системой авто
SETTING (SlaveModeEnable, NotFixed, bit_t, 0) // управление от штатной системы
SETTING (SlaveComfort, NotFixed, bit_t, 0) // управлять комфортом при постановке в Охрану по SLAVE.
SETTING (DisarmEmergPinVal, NotFixed, uint16_t, 1111) // ПИН-код для аварийного снятия с охраны
SETTING_RSRV(ArmAutoReadyNote) // предупреждение о готовности к автопостановке
SETTING (SlaveDisarmWithTagOnly,NotFixed, bit_t, 0) // снятие с охраны по SLAVE-входу только при наличии телефона-метки, прерывание тревоги не запрещает
SETTING_RSRV(ArmReserved = 0x01BF)
// настройки режима "тревога": 0x01C0 (448)
SETTING (AlarmDoorsDeciseconds, NotFixed, uint8_t, defAlarmDoorsDeciseconds) // Задержка тревоги по входам дверей (*100мс)
SETTING (AlarmTrunkDeciseconds, NotFixed, uint8_t, defAlarmTrunkDeciseconds) // Задержка тревоги по входам багажника (*100мс)
SETTING (KillEngineDeciseconds, Fixed, uint8_t, defKillEngineDeciseconds) // Период выдачи команды <ccKillEngine>: 0:Single; >127:OFF..
SETTING_RSRV(AlarmReserved = 0x01DF)
// настройки режима "хайджек" и работы с Меткой: 0x01E0 (480)
SETTING_RSRV(TagsRSSI) // Значения уровней RSSI метки для Автопостановки/Автоснятия
SETTING_RSRV(HijackReserved = 0x01FF)
// настройки режима "иммобилайзер": 0x0200 (512)
SETTING (Immobilizer, NotFixed, bit_t, 0) // функция иммобилайзер
SETTING_RSRV(ImmoReserved = 0x021F)
// настройки режима "автосервис": 0x0220 (544)
// не используются
SETTING_RSRV(ServiceReserved = 0x023F)
// настройки автозапуска: 0x0240 (576)
SETTING (TurboTimerIndex, NotFixed, uint8_t, defTurboTimerIndex) // индекс массива настроек турботаймера: 0=Off, 1=On, 2=Auto
SETTING (ReadyMinutes, NotFixed, uint8_t, defReadyMinutes) // длительность режима READY, в минутах
SETTING (SupportMinutes, NotFixed, uint8_t, defSupportMinutes) // длительность режима SUPPORT, в минутах
SETTING (PitStopTimeIndex, NotFixed, uint8_t, defPitStopTimeIndex)// индекс массива длительностей режима PITSTOP
SETTING (PreHeaterMinutes, NotFixed, uint8_t, defPreHeaterMinutes)// длительность работы PreHeater, в минутах
SETTING (SSB, NotFixed, bit_t, 0) // StartStopButton
SETTING_RSRV(WakeUpBySSB)//, NotFixed, bit_t, 0) // Будить автомобиль нажатием на кнопку SSB
SETTING (SetReadyMode, NotFixed, uint8_t, defSetReadyMode) // режим включения поддержки зажигания
SETTING (SkipPreStartMode, Fixed, bit_t, 0) // сразу же (без проверки статусов автомобиля) запустить двигатель - только для SSB!
SETTING (PowerStart, NotFixed, bit_t, 0) // запуск автомобиля с SSB по силе - только для SSB!
SETTING (ManualAttempts, NotFixed, uint8_t, defManualAttempts) // кол-во попыток запуска по команде с Брелока
SETTING (ReadyDisableImmBypass, NotFixed, bit_t, 1) // запрет включения обходчика при включении поддержки
SETTING (CrankAuxIgnOff, NotFixed, bit_t, 1) // выключать выход <AuxIgn> во время работы <oCrank>
SETTING (SupportImmBypassOff, NotFixed, bit_t, 1) // выключать обходчик после успешного пуска двигателя
SETTING (StopByDisarm, NotFixed, bit_t, 0) // глушить при снятии с охраны
SETTING (ClrReadyMode, NotFixed, uint8_t, defClrReadyMode) // режим выключения поддержки зажигания
SETTING (AutostartShockEnable, NotFixed, bit_t, 0) // разрешение тревоги по датчику удара в режимах Автозапуска
SETTING (PrestartSSB, NotFixed, uint8_t, defPrestartSSB) // Максимальное кол-во нажатий на SSB в PRESTART: 0-по умолчанию
SETTING (StopSSB, NotFixed, uint8_t, defStopSSB) // Максимальное кол-во нажатий на SSB в STOP: 0-по умолчанию
SETTING (CrankDelaySeconds, NotFixed, uint8_t, defCrankDelaySeconds) // Задержка перед включением стартера, в секундах
SETTING (AutostartBatteryLevel, NotFixed, uint8_t, defAutoStartBatteryLevel) // автозапуск при разряде аккумулятора (десятые доли вольта)
SETTING (AutostartTemperature, NotFixed, int8_t, defAutoStartTemperature) // автозапуск по температуре салона
SETTING_RSRV(MorningRun) // утренний запуск
SETTING_RSRV(EveningRun) // вечерний запуск
SETTING (DailyRunCountIndex, NotFixed, uint8_t, defDailyRunCountIndex) // индекс массива настроек кол-ва суток действия таймерных запусков: бесконечность<0, отключить все таймерные запуски=0.
SETTING (AutomaticsPeriodIndex, NotFixed, uint8_t, defAutomaticsPeriodIndex) // индекс массива настроек таймеров блокировки автоматических запусков
SETTING (AutomaticsLimitIndex, NotFixed, uint8_t, defAutomaticsLimitIndex) // индекс массива настроек ограничителей автоматических запусков за сессию Охраны
SETTING (EngineStartPercent, NotFixed, uint8_t, defEngineStartPercent) // процент от ХХ*2 для детектора состояния запущенного двигателя
SETTING (EngineRunPercent, NotFixed, uint8_t, defEngineRunPercent) // процент от ХХ*2 для детектора состояния работающего двигателя
SETTING (TurboTimerPercent, NotFixed, uint8_t, defTurboTimerPercent) // процент от ХХ*2 для детектора состояния работающего двигателя
SETTING (TimerRun0, NotFixed, TStartTimerSetting, {0x8000, 0}) // таймерный запуск
SETTING (TimerRun1, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun2, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun3, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun4, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun5, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun6, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun7, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun8, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun9, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun10, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun11, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun12, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (TimerRun13, NotFixed, TStartTimerSetting, {0x8000, 0})
SETTING (SlaveStartStop, NotFixed, bit_t, 1) // Запуск/Останов двигателя по SLAVE команде со штатного брелока
SETTING (ExternalHeatersEnable, NotFixed, bit_t, 1) // разрешение управлять внешними нагревателями
SETTING (ExternalHeatersTemperature,NotFixed, int8_t, defExternalHeatersTemperature) // пороговая температура включения нагревателя
SETTING (ExternalTemperatureSensorType,NotFixed,uint8_t, 0) // Тип внешнего датчика температуры (0=SEMITEC 103AT-2; 1=MF52A103J3950)
SETTING_RSRV(AutoStartReserved = 0x027F)
// настройки обработчика Акселерометра: 0x0280 (640)
SETTING (ShockNotify, NotFixed, uint8_t, 6) // чувствительность предупреждения по датчику Удара [2..9]
SETTING (ShockAlarm, NotFixed, uint8_t, 5) // чувствительность тревоги по датчику Удара [1..8]
SETTING (TiltAlarm, NotFixed, uint8_t, 5) // чувствительность тревоги по датчику Наклона [1..9]
SETTING (MotionAlarm, NotFixed, uint8_t, 5) // чувствительность тревоги по датчику Передвижения/Перемещения [1..9]
SETTING (EmergencyBraking, NotFixed, uint8_t, defEmergencyBraking) // 0-ничего не делать; 1-только моргать; 2-моргать и отпиреть ЦЗ;
// Формат вышеуказанных полей состоит в том, что старший бит - это флажок Disable.
// Т.е. если он стоит, то датчик с указанным уровнем чувствительности выключен.
SETTING (ShockSensTable, NotFixed, uint8_t, 0) // Индекс таблицы чувствительностей (варианты шкал чувствительностей)
//SETTING_ALIAS(AccelSTART = ShockNotify)
SETTING_RSRV(AccelLAST = 0x029F)
#ifdef MOBICAR_3
// настройки Абонентских оповещений: 0x02A0 (672)
SETTING_RSRV(PhoneNumber1) // телефонный номер 1го абонента
SETTING_RSRV(PhoneNumber2) // телефонный номер 2го абонента
SETTING_RSRV(PhoneNumber3) // телефонный номер 3го абонента
SETTING_RSRV(PhoneNumber4) // телефонный номер 4го абонента
SETTING_RSRV(SMS1) // SMS оповещения 1го абонента
SETTING_RSRV(SMS2) // SMS оповещения 2го абонента
SETTING_RSRV(SMS3) // SMS оповещения 3го абонента
SETTING_RSRV(SMS4) // SMS оповещения 4го абонента
SETTING_RSRV(Call1) // Голосовые оповещения 1го абонента
SETTING_RSRV(Call2) // Голосовые оповещения 2го абонента
SETTING_RSRV(Call3) // Голосовые оповещения 3го абонента
SETTING_RSRV(Call4) // Голосовые оповещения 4го абонента
SETTING_RSRV(SubscriberNotifications = 0x02AF)
// настройки Модема: 0x02B0 (688)
SETTING_RSRV(USSD) // USSD запрос
SETTING_RSRV(VoiceRoamEnable) // разрешены голосовые оповещения в роуминге
SETTING_RSRV(DataRoamEnable) // разрешена передача данных по GPRS в роуминге
SETTING_RSRV(SMSRoamEnable) // разрешена отправка SMS в роуминге
SETTING_RSRV(WaitAnswerTimeout) // время ожидания ответа абонента при оповещении, сек
SETTING_RSRV(CallEndTimeout) // таймаут окончания звонка при бездействии абонента, сек
SETTING_RSRV(TripEndTimeout) // таймаут окончания поездки при выключении зажигания, сек
SETTING_RSRV(LowBatteryVoltage) // уровень входного напряжения генерации оповещения (десятые доли вольта)
SETTING_RSRV(ModemBaseOptions = 0x02BF)
// настройки Модема расширенные: 0x02C0 (704)
SETTING_RSRV(ParkingLocRequest) // определять место парковки по БС
SETTING_RSRV(TripLocTimeout) // интервал запроса информации по БС во время поездки, *10сек (=0 не определять)
SETTING_RSRV(EvacLocTimeout) // интервал запроса информации по БС во время эвакуации, *10сек (=0 не определять)
SETTING_RSRV(SMSLoc) // добавлять координаты в SMS
SETTING_RSRV(TimeZone) // Часовой пояс, в часах
SETTING_RSRV(Internet) // признак версии PRO (соединение по Internet)
SETTING_RSRV(ModemAPN) // Строка APN
SETTING_RSRV(ModemLogin) // Строка Login
SETTING_RSRV(ModemPassword) // Строка Password
SETTING_RSRV(DTCRequestTimeout) // интервал времени после выключения зажигания для запроса DTC, *1сек (=0 не определять)
SETTING_RSRV(ClockSyncMode) // Режим синхронизации Системных часов: 0=OFF, 1=PhoneClock, 2=NetworkClock
SETTING_RSRV(TimeZoneSyncMode) // Режим синхронизации Системной зоны: 0=OFF, 1=PhoneTimeZone, 2=NetworkTimeZone
#endif
SETTING_RSRV(ModemExtOptions = 0x02CF)
SETTING_RSRV(CoreReserved = 0x05EF)
// настройки 0x5F0 .. 0x5FF - настройки ядра под CAN-прошивку
SETTING (iCanAvail_Mask, Fixed, uint32_t, 0) // входы, доступные в CAN-прошивке, битовая маска
SETTING (oCanAvail_Mask, Fixed, uint64_t, 0) // выходы, доступные в CAN-прошивке, битовая маска
SETTING (valCanAvail_Mask, Fixed, uint32_t, 0) // числовые значения, доступные в CAN-прошивке, битовая маска
SETTING (valCanEn_Mask, NotFixed, uint32_t, 0) // используемые числовые значения из CAN-прошивки, битовая маска
#undef SETTING
#undef SETTING_RSRV
#undef SETTING_ALIAS

83
libs/SysTimer.h Normal file
View File

@@ -0,0 +1,83 @@
#ifndef SYSTIMER_H
#define SYSTIMER_H
#include <cstdint>
#include "CanFwInterface.h"
// миллисекундный таймер. Макс. таймаут - 2**32 мс.
class TimerMs {
public:
typedef uint32_t T_Timer;
TimerMs()
{ Restart(); }
virtual ~TimerMs()
{ }
virtual inline T_Timer Restart(void)
{
auto prev = _tmr;
_tmr = CntValue();
return _tmr - prev;
}
inline T_Timer Value(void) const
{ return CntValue() - _tmr; }
inline T_Timer Rest(const T_Timer timeout) const
{
T_Timer elapsed = Value();
if (elapsed < timeout)
return timeout - elapsed;
return 0;
}
inline bool CheckTimeout(const T_Timer timeout) const
{ return Value() > timeout; }
private:
T_Timer _tmr;
static inline T_Timer CntValue(void)
{ return CoreFunc->GetTickMs(); }
};
class TimerMsOnce : public TimerMs
{
public:
TimerMsOnce() : TimerMs()
{ started = true; }
virtual ~TimerMsOnce()
{ }
virtual inline T_Timer Restart(void)
{
auto elapsed = TimerMs::Restart();
started = true;
return elapsed;
}
inline bool IsStarted(void) const
{ return started; }
inline void Stop(void)
{ started = false; }
virtual inline bool CheckTimeout(T_Timer timeout)
{
if (started)
{
if (Value() <= timeout)
return false;
Stop();
}
return true;
}
private:
bool started;
};
#endif // SYSTIMER_H

73
libs/Utils.h Normal file
View File

@@ -0,0 +1,73 @@
/*
* Utils.h
*
* Created on: 29 мая 2015 г.
* Author: esaulenko
*/
#ifndef UTILS_H_
#define UTILS_H_
#include <cstdint>
#include "IO.h"
uint32_t constexpr BIT (uint32_t n)
{ return 1UL << n; }
uint64_t constexpr BIT64 (uint32_t n)
{ return 1ULL << n; }
template <typename T1, typename T2> uint32_t MAX (T1 a, T2 b)
{
if (a > b) return a;
else return b;
}
template <typename T1, typename T2> uint32_t MIN (T1 a, T2 b)
{
if (a > b) return b;
else return a;
}
#define countof(array) (sizeof(array)/sizeof(array[0]))
// установка/снятие бита
template <typename T> void BSET (T &x, uint32_t bitNo) ///< установить бит
{ x |= BIT64 (bitNo); }
template <typename T> void BCLR (T &x, uint32_t bitNo) ///< стереть бит
{ x &= ~BIT64 (bitNo); }
///< определить (стереть (Value=0) или установить(Value=1)) бит
template <typename T> void BDEF (T &x, uint32_t bitNo, uint32_t Value)
{
if (Value) BSET (x, bitNo);
else BCLR (x, bitNo);
}
// возвращает номер старшего бита
constexpr int8_t bitmask2offset (uint32_t val)
{
return (int8_t) ( (val > 1) ? ( bitmask2offset (val/2) + 1 ) : 0 );
}
// управление последовательностями
// использовать в CoreFunc->RunSequence()
#define SEQ(x,y) CIO::x, CSettings::y-CSettings::seqOFFSET
#endif /* UTILS_H_ */

40
libs/WeakFunc.cpp Normal file
View File

@@ -0,0 +1,40 @@
#include "source/SourcePath.h"
#include SRC_HEADER
// функции-пустышки
// инициализирует ОЗУ, вызывается при старте контроллера
__attribute__((weak)) void Init (TCanFwMem * vars) { }
// Вызывается при изменении настроек (на каждую настройку)
__attribute__((weak)) void SettingChanged (TCanFwMem * vars, uint16_t id) { }
// принимает и обрабатывает пакет из CAN
__attribute__((weak)) void Can1Received (TCanFwMem * vars, TCanPkt *apPkt) { }
__attribute__((weak)) void Can2Received (TCanFwMem * vars, TCanPkt *apPkt) { }
// обрабатывает события изменения входов-выходов
__attribute__((weak)) void InputChanged (TCanFwMem * vars, uint32_t aInputNum, bool aSwitchedOn) { }
__attribute__((weak)) void OutputChanged (TCanFwMem * vars, uint32_t aOutputNum, bool aSwitchedOn) { }
__attribute__((weak)) void GuardEvent (TCanFwMem * vars, TGuardEvents aEvent) { }
// события начала и конца последовательностей
__attribute__((weak)) void SequenceStart (TCanFwMem * vars, uint32_t aEvent) { }
__attribute__((weak)) void SequenceStop (TCanFwMem * vars, uint32_t aEvent) { }
// команда от ядра
__attribute__((weak)) void Command (TCanFwMem * vars, TCanFwCommands aCmd, uint32_t aCmdParam) { }
// вызывается по таймауту
__attribute__((weak)) void PeriodicProcess (TCanFwMem * vars) { }
// LIN
__attribute__((weak)) void Lin1Received (TCanFwMem * vars, TLinFrame *apFrame) { }
__attribute__((weak)) void Lin2Received (TCanFwMem * vars, TLinFrame *apFrame) { }
__attribute__((weak)) void Lin1Transmitted (TCanFwMem * vars, uint8_t aFrameId) { }
__attribute__((weak)) void Lin2Transmitted (TCanFwMem * vars, uint8_t aFrameId) { }
// Mobicar3 LIN
__attribute__((weak)) void Lin3Received (TCanFwMem * vars, TLinFrame *apFrame) { }
__attribute__((weak)) void Lin3Transmitted (TCanFwMem * vars, uint8_t aFrameId) { }

17
src/CAN_FW.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef CAN_FW_H_
#define CAN_FW_H_
#include "Settings.h"
#include "Buffer.h"
#include "Periodic.h"
#include "Can.h"
#define CAN_FW_DESCRIPTION "Test"
// структура с пользовательскими переменными
struct TCanFwMem {
CSettings::TSettings Settings; // структура с настройками - должна быть всегда в начале
};
#endif /* CAN_FW_H_ */

22
src/CAN_Inputs.h Normal file
View File

@@ -0,0 +1,22 @@
#include "CAN_FW.h"
#include "Can.h"
#include "IO.h"
#include "Utils.h"
void Init (TCanFwMem * vars)
{
CoreFunc->DebugConsole("CAN_FW version: %s\n", (const char*)(gCanFwInfo.TextInfo));
static const TCanInit can1_init =
{
CCan::CanBaudrate500,
1,
{
CCan::Filter::List11 (0x660),
CCan::Filter::Mask11 (0x7E0, 0x7F0), // 0x7E0..0x7EF
}
};
CoreFunc->CanInit (CANch1, &can1_init);
}

5
src/CAN_Outputs.h Normal file
View File

@@ -0,0 +1,5 @@
#include "CAN_FW.h"
#include "Can.h"
#include "IO.h"
#include "Utils.h"

98
src/SettingsCANTable.h Normal file
View File

@@ -0,0 +1,98 @@
//=====================================================================================
// SETTING_RSRV позволяет сделать "дырки" в номерах настроек
// если не определена, значит, она не используется
#ifndef SETTING_RSRV
#define SETTING_RSRV(name)
#endif
//************************** Динамические параметры ***********************************************//
// числовые значения, доступные в CAN-прошивке, битовая маска
SETTING (valCanAvail_Mask, Fixed, uint32_t, \
BIT(CanData_RPM) | BIT(CanData_Speed) | BIT(CanData_Odometer) | BIT(CanData_Accelerator) | \
BIT(CanData_BrakeForce) | BIT(CanData_WheelAngle) | BIT(CanData_FuelLevel) | BIT(CanData_FuelConsumption) |
BIT(CanData_CoolantTemp) )
// используемые числовые значения из CAN-прошивки, битовая маска
SETTING (valCanEn_Mask, NotFixed, uint32_t, \
BIT(CanData_RPM) | BIT(CanData_Speed) | BIT(CanData_Odometer) | BIT(CanData_Accelerator) | \
BIT(CanData_BrakeForce) | BIT(CanData_WheelAngle) | BIT(CanData_FuelLevel) | BIT(CanData_FuelConsumption) |
BIT(CanData_CoolantTemp) )
//************************** ВХОДЫ ****************************************************************//
SETTING (iDoorDrv, NotFixed, TInputSettings, {CIO::iCAN}) // Дверь водителя
SETTING (iDoorFP, NotFixed, TInputSettings, {CIO::iCAN}) // Дверь пассажира
SETTING (iDoorRL, NotFixed, TInputSettings, {CIO::iCAN}) // Дверь задняя левая
SETTING (iDoorRR, NotFixed, TInputSettings, {CIO::iCAN}) // Дверь задняя правая
SETTING (iTrunk, NotFixed, TInputSettings, {CIO::iCAN}) // Багажник
SETTING (iACC, NotFixed, TInputSettings, {CIO::iCAN}) //
SETTING (iIgn, NotFixed, TInputSettings, {CIO::iCAN}) // Зажигание
SETTING (iBrake, NotFixed, TInputSettings, {CIO::iCAN}) // Педаль тормоза
SETTING (iHBrake, NotFixed, TInputSettings, {CIO::iCAN}) // Стояночный тормоз
SETTING (iPark, NotFixed, TInputSettings, {CIO::iCAN}) // АКПП в положении "Park"
SETTING (iLock, NotFixed, TInputSettings, {CIO::iCAN}) // Замки дверей
SETTING (iLamp, NotFixed, TInputSettings, {CIO::iCAN}) // Габариты / фары
SETTING (iLeftTurnLight, NotFixed, TInputSettings, {CIO::iCAN}) // Левый поворотник
SETTING (iRightTurnLight, NotFixed, TInputSettings, {CIO::iCAN}) // Правый поворотник
SETTING (iTaho, NotFixed, TInputSettings, {CIO::iCAN}) // Тахометр
// SETTING (iEmergency, NotFixed, TInputSettings, {CIO::iCAN}) // Используется как статус
SETTING (Kxx, NotFixed, uint16_t, 37) // Калибровочный коэф. холостого хода
//************************** ВЫХОДЫ ************************************************************//
SETTING (oLights, NotFixed, uint32_t, oBIT(oCAN))
// SETTING (oAutoStart, NotFixed, uint32_t, oBIT(oCAN)) // События автозапуска
// SETTING (oEmergency, NotFixed, uint32_t, oBIT(oBrownViolet)) // Выход на триггерную кнопку.
SETTING (oKLine1Relay, NotFixed, uint32_t, 0)
SETTING (oKLine2Relay, NotFixed, uint32_t, 0)
SETTING (oLockDoors, NotFixed, uint32_t, oBIT(oCAN)) // Запереть все двери
SETTING (oUnlockDoors, NotFixed, uint32_t, oBIT(oCAN)) // Отпереть все двери
SETTING (oImmBypass, NotFixed, uint32_t, oBIT(oBrownWhite))
SETTING (oBrake, NotFixed, uint32_t, oBIT(oBrownYellow))
SETTING (oIgn, NotFixed, uint32_t, 0) // Включение зажигания
SETTING (oAuxIgn, NotFixed, uint32_t, 0) // Дополнительная линия зажигания
SETTING (oAcc, NotFixed, uint32_t, 0) // Аксессуары
SETTING (oCrank, NotFixed, uint32_t, 0) // Стартер
//--------- Check boxs -----------------------------------------------------------------//
SETTING (SSB, NotFixed, bit_t, 1)
SETTING (DriveBuiltinSystem, NotFixed, bit_t, 1) // управлять штатной системой автомобиля
SETTING (SlaveModeEnable, NotFixed, bit_t, 1) // включить слейв
SETTING (SlaveDisarmWithTagOnly,NotFixed, bit_t, 1) // снятие с охраны по SLAVE-входу только при наличии телефона-метки, прерывание тревоги не запрещает
SETTING (SetReadyMode, NotFixed, uint8_t, 2) // режим включения поддержки зажигания
SETTING (ClrReadyMode, NotFixed, uint8_t, 1)
SETTING (LightsArm, NotFixed, bit_t, 0) // при включении охраны
SETTING (LightsDisarm, NotFixed, bit_t, 0) // при выключении охраны
//--------- Последовательности --------------------
SETTING (seqProg6, NotFixed, TSequence, {qMS(100),6})
SETTING (seqProg8, Fixed, TSequence, {qMS(10),25}) // аварийка: импульс 250 мс
SETTING (seqProg9, Fixed, TSequence, {qMS(10),15}) // аварийка: импульс 150 мс
//--------- Переименование входов/выходов ---------
// SETTING_NAME (iEmergency, "<Аварийная сигнализация>")
// SETTING_NAME (oEmergency, "<Управление поворотниками через кнопку>")
// SETTING_NAME (oWireLock, "<Запирание дверей при IgnOn>")
// SETTING_NAME (oWireUnlock, "<Отпирание дверей при IgnOn>")
//************************** Настройки CAN-прошивки ***********************************************//
SETTING_CAN (SET1, NotFixed, bit_t, 0, "Настройка 1")
SETTING_CAN (SET2, NotFixed, uint8_t, 0, "Настройка 2|Вкл|Выкл")
SETTING_CAN (SET3, NotFixed, uint8_t, 1, "Настройка 3|Вкл|Выкл|He знаю")
#undef SETTING
#undef SETTING_RSRV
#undef SETTING_ALIAS
#undef SETTING_CAN
//************************** The End **************************************************************//

16
src/immo/Immo.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef __IMMO_H_
#define __IMMO_H_
#include <cstdint>
#include <stdio.h>
#include <cstring>
void CalcUDS(uint8_t *sec_ask, uint8_t *sec_ans );//функция для расчёта security access
void GetImmoOut(uint8_t *req, uint8_t *ans, uint8_t *key );
void shortGetImmoOut(uint8_t *state, uint8_t *key);
bool CheckArray(uint8_t *a,uint8_t *b, uint8_t len);
bool CheckKey(uint8_t *req, uint8_t *ans, uint8_t *key );
#endif /* __IMMO_H_ */

30
src/immo/immo.cpp Normal file
View File

@@ -0,0 +1,30 @@
#include "Immo.h"
void CalcUDS(uint8_t *sec_ask, uint8_t *sec_ans )//функция для расчёта security access
{
}
void GetImmoOut(uint8_t *req, uint8_t *ans, uint8_t *key )
{//функция для расчёта ответа иммо
}
void shortGetImmoOut(uint8_t *state, uint8_t *key)
{//функция для расчёта ответа иммо
}
bool CheckArray(uint8_t *a,uint8_t *b, uint8_t len)
{
uint8_t count=0;
for(int i=0;i<len;i++)
{
if(a[i]==b[i])
count++;
}
if(count>=len-1)
return 1;
return 0;
}
bool CheckKey(uint8_t *req, uint8_t *ans, uint8_t *key )
{ //функция для проверуи валидности ключа при обучении
unsigned char state[16] = { 0 };
return CheckArray(state, ans, 8);
}

1
src/immo/immo.md Normal file
View File

@@ -0,0 +1 @@
# Обход штатного иммобилайзера

11
src/source/SourcePath.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef SOURCEPATH_H_
#define SOURCEPATH_H_
// здесь указываются пути к конкретной прошивке, которую необходимо собрать
#define SRC_HEADER "CAN_FW.h"
#define SRC_SETTINGS "SettingsCANTable.h"
#define SRC_FILE1 "CAN_Inputs.h"
#define SRC_FILE2 "CAN_Outputs.h"
#endif /* SOURCEPATH_H_ */

147
sys/M1_CAN_FW.ld Normal file
View File

@@ -0,0 +1,147 @@
/*************************************************
* linker script for STM32F10xCL
************************************************/
ENTRY (CanFuctTable)
MEMORY
{
/* оперативку не используем! */
/* RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0 */
/* используем флеш 112K .. 128K */
FLASH (rx) : ORIGIN = (0x08000000 + 112K), LENGTH = 16K
}
/* higher address of the user mode stack */
PROVIDE ( _estack = ALIGN(ORIGIN(RAM) + LENGTH(RAM) - 8 ,8) );
SECTIONS
{
.entrance_vector :
{
_stext = .;
. = ALIGN(4);
KEEP(*(.entrance_vector))
. = ALIGN(4);
} > FLASH =0xFFFFFFFF
.text :
{
__ctors_start__ = .;
KEEP(SORT(*)(.init_array)) /* eabi uses .init_array for static constructor lists */
__ctors_end__ = .;
__dtors_start__ = .;
__dtors_end__ = .;
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*)
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.eh_frame_hdr)
*(.eh_frame)
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.gcc_except_table)
*(.eh_frame_hdr)
*(.eh_frame)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
} > FLASH =0xFFFFFFFF
/* .ARM.exidx is sorted, so has to go in its own output section. */
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH =0xFFFFFFFF
__exidx_end = .;
.text.align :
{
. = ALIGN(8);
_etext = .;
_sidata = _etext; /* start of initialized data label */
} > FLASH =0xFFFFFFFF
/* конец данных во флеш - кладём сюда таблицу с настройками и контрольную сумму */
.text.SettingsCanName :
{
. = ALIGN(4);
KEEP(*(.SettingsCanName))
} > FLASH
.text.SettingsVarName :
{
. = ALIGN(4);
KEEP(*(.SettingsVarName))
} > FLASH
.text.SettingsTable :
{
. = ALIGN(4);
KEEP(*(.SettingsTable))
} > FLASH
.text.CheckSum :
{
. = ALIGN(4);
KEEP(*(.CheckSum))
} > FLASH
/**************************************************************
* Remove the debugging information from the standard libraries
***************************************************************/
/* remove the debugging information from the standard libraries */
DISCARD :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/*
* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0.
*/
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

147
sys/M3_CAN_FW.ld Normal file
View File

@@ -0,0 +1,147 @@
/*************************************************
* linker script for STM32F4xx
************************************************/
ENTRY (CanFuctTable)
MEMORY
{
/* оперативку не используем! */
/* RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0 */
/* используем флеш 48K .. 64K */
FLASH (rx) : ORIGIN = (0x08000000 + 48K), LENGTH = 16K
}
/* higher address of the user mode stack */
PROVIDE ( _estack = ALIGN(ORIGIN(RAM) + LENGTH(RAM) - 8 ,8) );
SECTIONS
{
.entrance_vector :
{
_stext = .;
. = ALIGN(4);
KEEP(*(.entrance_vector))
. = ALIGN(4);
} > FLASH =0xFFFFFFFF
.text :
{
__ctors_start__ = .;
KEEP(SORT(*)(.init_array)) /* eabi uses .init_array for static constructor lists */
__ctors_end__ = .;
__dtors_start__ = .;
__dtors_end__ = .;
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*)
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.eh_frame_hdr)
*(.eh_frame)
*(.ARM.extab* .gnu.linkonce.armextab.*)
*(.gcc_except_table)
*(.eh_frame_hdr)
*(.eh_frame)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
} > FLASH =0xFFFFFFFF
/* .ARM.exidx is sorted, so has to go in its own output section. */
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH =0xFFFFFFFF
__exidx_end = .;
.text.align :
{
. = ALIGN(8);
_etext = .;
_sidata = _etext; /* start of initialized data label */
} > FLASH =0xFFFFFFFF
/* конец данных во флеш - кладём сюда таблицу с настройками и контрольную сумму */
.text.SettingsCanName :
{
. = ALIGN(4);
KEEP(*(.SettingsCanName))
} > FLASH
.text.SettingsVarName :
{
. = ALIGN(4);
KEEP(*(.SettingsVarName))
} > FLASH
.text.SettingsTable :
{
. = ALIGN(4);
KEEP(*(.SettingsTable))
} > FLASH
.text.CheckSum :
{
. = ALIGN(4);
KEEP(*(.CheckSum))
} > FLASH
/**************************************************************
* Remove the debugging information from the standard libraries
***************************************************************/
/* remove the debugging information from the standard libraries */
DISCARD :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/*
* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0.
*/
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

42416
sys/STM32F107.svd Normal file

File diff suppressed because it is too large Load Diff

56913
sys/STM32F446.svd Normal file

File diff suppressed because it is too large Load Diff

70
sys/allowed_signers.sh Executable file
View File

@@ -0,0 +1,70 @@
#!/bin/sh
# Скрипт для обновления ключей для проверки подписей коммитов
if ! git --version > /dev/null 2>&1; then
printf "\n\033[0;31mGIT is not found!\033[0m\n"; exit 1;
fi
if ! git status > /dev/null 2>&1; then
printf "\n\033[0;31mThis is not a git repo!\033[0m\n"; exit 1;
fi
domain=$(git remote -v | head -n 1 | tr '\t' ' ' | cut -d ' ' -f2)
domain=$(echo "$domain" | sed 's/.*@//' | sed 's/:.*//')
echo "Repo domain: $domain"
login=$1
password=$2
if [ -z "$login" ]; then
printf "Enter login: "
read -r login
fi
if [ -z "$password" ]; then
stty -echo
printf "Enter password: "
read -r password
stty echo
printf "\n"
fi
apitest=$(curl -s -u "$login:$password" "https://$domain/api/v1/user")
# echo "apitest: $apitest"
if echo "$apitest" | grep -- 'user does not exist' >/dev/null 2>&1; then
printf "\033[0;31mERROR: User \"%s\" does not exist on %s\033[0m\n" "$login" "$domain"; exit 1;
fi
if echo "$apitest" | grep -- 'password is invalid' >/dev/null 2>&1; then
printf "\033[0;31mERROR: Invalid password\033[0m\n"; exit 1;
fi
allowed_signers_file=~/.ssh/allowed_signers
if [ ! -f "$allowed_signers_file" ]; then
echo "Create $allowed_signers_file"
touch $allowed_signers_file
fi
users=$(git shortlog -snc --all | tr '\t' ' ' | sed 's/^ *//' | cut -d ' ' -f2)
echo "Repo users: $users" | tr "\n" ' '; echo
echo "" > test.txt
for user in $users; do
keys=$(curl -s -u "$login:$password" "https://$domain/api/v1/users/$user/keys")
keys=$(echo "$keys" | tr , '\n' | grep -E -- '^"key":".*' | sed 's/^"key"://' | tr -d '\n')
IFS='"'
for key in $keys; do
if [ "$key" = "" ]; then continue; fi
if grep -Fq "$key" "$allowed_signers_file"; then continue; fi
echo "New key for $user"
printf "%s %s\n" "$user" "$key" >> $allowed_signers_file
done
unset IFS
done
echo "$allowed_signers_file updated"

38
sys/changelog.sh Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/sh
# Скрипт генерирует changelog от последнего релиза.
CHANGELOG=CHANGELOG.md
printf "\033[0;32m~~~ %s generation ~~~\033[0m\n" "$CHANGELOG";
if ! git --version > /dev/null 2>&1; then
printf "\n\033[0;31mGIT is not found!\033[0m\n"; exit 1;
fi
if ! git status > /dev/null 2>&1; then
printf "\n\033[0;31mThis is not a git repo!\033[0m\n"; exit 1;
fi
# Get all tags that points to the HEAD
CURRENT_TAG=$(git tag --points-at HEAD)
echo "Current tag: $CURRENT_TAG"
LAST_TAG=$(git describe --tags --abbrev=0 HEAD^ 2> /dev/null)
echo "Last tag: $LAST_TAG"
if [ -n "$CURRENT_TAG" ]; then
printf "<details><summary>changelog:</summary>\n\n" > $CHANGELOG
else
printf "Current commit does not have a release tag.\n\n" > $CHANGELOG
fi
if [ -n "$LAST_TAG" ]; then
git log --pretty="- %h %s" "$LAST_TAG..HEAD" >> $CHANGELOG
else
git log --pretty="- %h %s" >> $CHANGELOG
fi
if [ -n "$CURRENT_TAG" ]; then
printf "</details>" >> $CHANGELOG
fi

4
sys/export.bat Normal file
View File

@@ -0,0 +1,4 @@
@echo off
chcp 65001 > nul
set "PATH=%USERPROFILE%\.xpack-dev-tools\xpack-windows-build-tools-4.4.1-2\bin;%PATH%"
set "PATH=%USERPROFILE%\.xpack-dev-tools\xpack-arm-none-eabi-gcc-12.3.1-1.2\bin;%PATH%"

3
sys/export.ps1 Normal file
View File

@@ -0,0 +1,3 @@
chcp 65001 > $null
$env:PATH = "$env:UserProfile\.xpack-dev-tools\xpack-windows-build-tools-4.4.1-2\bin;" + $env:PATH
$env:PATH = "$env:UserProfile\.xpack-dev-tools\xpack-arm-none-eabi-gcc-12.3.1-1.2\bin;" + $env:PATH

17
sys/export.sh Normal file
View File

@@ -0,0 +1,17 @@
# This script should be sourced, not executed.
# shellcheck disable=SC2148,SC1091,SC3010
if echo "$0" | grep -- "bash" >/dev/null; then
if [ -f "$HOME/.bash_profile" ]; then . "$HOME/.bash_profile"; fi
fi
if uname | grep -- "MINGW64" >/dev/null 2>&1; then
chcp.com 65001 > /dev/null
PATH=~/.xpack-dev-tools/xpack-windows-build-tools-4.4.1-2/bin:$PATH
fi
if uname | grep -- "Darwin" >/dev/null 2>&1; then
PATH=/opt/homebrew/opt/make/libexec/gnubin:$PATH
fi
PATH=~/.xpack-dev-tools/xpack-arm-none-eabi-gcc-12.3.1-1.2/bin:$PATH

4
sys/export.zsh Normal file
View File

@@ -0,0 +1,4 @@
# This script should be sourced, not executed.
export PATH=/opt/homebrew/opt/make/libexec/gnubin:$PATH
export PATH=~/.xpack-dev-tools/xpack-arm-none-eabi-gcc-12.3.1-1.2/bin:$PATH

184
sys/hex2fw.sh Executable file
View File

@@ -0,0 +1,184 @@
#!/bin/sh
# shellcheck disable=SC2034,SC2317
# Скрипт преобразования hex в fw.
# В качестве параметра принимает путь к файлу hex.
# https://srecord.sourceforge.net/
# https://manpages.ubuntu.com/manpages/xenial/man1/srec_cat.1.html
# https://manpages.ubuntu.com/manpages/xenial/man1/srec_examples.1.html
# echo -e "\033[0;32m~~~ Hex to FW ~~~\033[0m";
PATH=$(pwd)/$(dirname "$0")/srecord:$PATH
PATH="C:/Program Files/Git/usr/bin/":$PATH
#========================== Functions ==========================
# ByteString - ascii string with bytes separated by spaces like "00 11 22 33"
HexStringToByteString() { printf "%s" "$1" | od -An -t x1 | tr -d '\n' | tr 'a-f' 'A-F' | awk '{$1=$1};1' | tr -d '\n'; }
GetRandomByteString() { openssl rand "$1" | od -An -t x1 | tr -d '\n' | tr 'a-f' 'A-F' | awk '{$1=$1};1' | tr -d '\n'; }
IntelHexFileToByteString()
{
T=$(srec_cat "$1" -intel -fill 0xFF -over "$1" -intel -address-length=4 -o - -ascii_hex)
res1=0x$(echo "$T" | head -n 1 | cut -f1 -d , | sed "s/.*\$A//") # Output: start addr
T=$(echo "$T" | tr -d '\r' | tr '\n' ' ' | tr '\002\003' ',')
T=$(echo "$T" | cut -f3 -d , | awk '{$1=$1};1') # (awk '{$1=$1};1' - remove leading, trailing and extra spaces between fields)
res2=$(echo "$T" | wc -w) # Output: size in bytes
res3=$T # Output: byte string
}
# parmeters: addr fieldsnum string
GetFieldsFromByteString() { echo "$3" | cut -d ' ' -f "$1"-$(($1 + $2 - 1)); }
# parmeters: addr fieldsnum string
GetHexFromByteString() { printf 0x; GetFieldsFromByteString "$1" "$2" "$3" | awk '{print $4,$3,$2,$1}' | tr -d ' '; }
# parmeters: addr fieldsnum string
GetStringFromByteString() { GetFieldsFromByteString "$1" "$2" "$3" | xxd -r -p | tr -d '\000'; }
ByteStringToAsciiHex()
{
printf "\002 \$A%08X,\n" "$1" # Start and Address
echo "$2" | fold -s -w48 | awk '{$1=$1};1' # Data (awk '{$1=$1};1' - remove leading, trailing and extra spaces between fields)
printf "\003" # The End
}
CRC32_FromByteString()
{
# CAN прошивка использует кривой MPEG2 CRC32 по историческим причинам
# В будущем надо исправить на нормальный CRC32 от STM32
T=$(ByteStringToAsciiHex 0x10000000 "$1")
T=$(echo "$T" | srec_cat - -ascii_hex -Bit_Reverse 4 -stm32 0 -Bit_Reverse 4 -xor 0xFF -o -ascii_hex)
echo "$T" | tr -d '\002\003' | head -n 2 | tail -n 1 | cut -d ' ' -f1-4
}
HexToByteString() { echo "$1" | sed 's/^0x//' | fold -w2 | tac | tr '\n' ' ' | sed 's/ $//'; }
#========================== Main code ==========================
IntelHexFileToByteString "$1"
fw_start_addr=$res1
# echo "fw_start_addr $fw_start_addr"
fw_size=$res2
# echo "fw_size $fw_size"
fw_data=$res3
# echo "fw_data: $fw_data"
# выкидываем последние 4 байта и дописываем наше CRC
fw_data=$(GetFieldsFromByteString 1 $((fw_size - 4)) "$fw_data")
crc=$(CRC32_FromByteString "$fw_data")
fw_data="$fw_data $crc"
# echo "fw_data: $fw_data"
struct_addr=$(GetHexFromByteString 1 4 "$fw_data")
# echo "struct_addr $struct_addr"
struct_offset=$(( struct_addr - fw_start_addr ))
# echo "struct_offset $struct_offset"
# // Структура массива информации о CAN-прошивке
# struct TCanFwInfo {
# TVersion Version; // Версия ПО
# uint32_t Build; // Хеш коммита в репозитории git
# uint32_t const * pCRC32; // Адрес, где расположена CRC32
# uint32_t reserved2;
# uint8_t TextInfo[64]; // Текстовая информация
# } __attribute__((packed, aligned(4)));
# // описание прошивки
# const TCanFwInfo gCanFwInfo =
# {
# (CAN_FW_VERSION << 24) | BUILD_DATE, // Version - Версия ПО
# GIT_BUILD, // Хеш коммита в репозитории git
# &CanChksum, // *pCRC32 - Адрес, где расположена CRC32
# 0, // reserved2
# M_NAME CAN_FW_DESCRIPTION "_" GIT_VERSION // TextInfo[64] - Текстовая информация
# };
index=$(( struct_offset + 1 ))
day=$(GetFieldsFromByteString "$index" 1 "$fw_data")
# echo "day: $day"
index=$(( index + 1 ))
mounth=$(GetFieldsFromByteString "$index" 1 "$fw_data")
# echo "mounth: $mounth"
index=$(( index + 1 ))
year=$(GetFieldsFromByteString "$index" 1 "$fw_data")
# echo "year: $year"
index=$(( index + 1 ))
can_fw_version=$(GetFieldsFromByteString "$index" 1 "$fw_data")
# echo "can_fw_version: $can_fw_version"
index=$(( index + 1 ))
git_build=$(GetFieldsFromByteString "$index" 4 "$fw_data")
# echo "git_build: $git_build"
index=$(( index + 4 ))
CRC_addr=$(GetHexFromByteString "$index" 4 "$fw_data")
# echo "CRC_addr: $CRC_addr"
index=$(( index + 8 ))
text_info=$(GetStringFromByteString "$index" 64 "$fw_data")
# echo "text_info: $text_info"
# Версия git в последнем поле после '_'
git_version=$(echo "$text_info" | awk -F '_' '{print $NF}')
# echo "git_version: $git_version"
# struct TFirmwareHdr {
# uint32_t ChckSum; // вычисляется по всем нижеследующим полям и данным
# uint32_t Type; // тип прошивки
# uint32_t Version; // версия/дата
# uint32_t Build; // Билд прошивки
# uint32_t Len; // длина данных
# uint32_t Offset; // смещение прошивки во flash
# uint8_t InitVect[8]; // Случайное число, используется при дешифровании
# }; // sizeof() = 32
# struct TFirmwareFileHdr {
# uint8_t Sign[8]; // fixed to 'MOBICAR '
# uint8_t Desc[64]; // текстовое описание
# uint8_t pad1[24]; // дополнение до 96 байт
# TFirmwareHdr bin_hdr;
# }; // sizeof() = 128
# hdr1 - заголовок до CRC
hdr1="MOBICAR version $can_fw_version$year$mounth$day, $day.$mounth.$year, GIT = $git_version"
# echo "hdr1: $hdr1"
length=$(( ${#hdr1} ))
# echo "length: $length"
hdr1=$(HexStringToByteString "$hdr1")
# Добиваем остаток до TFirmwarehdr (8+64+24=96)
for i in $(seq $(( length + 1 )) 96); do
hdr1="$hdr1 00"
done
# printf "hdr1:\n%s\n" "$hdr1"
# hdr2 - заголовок после CRC
hdr2="02 00 00 00" # тип прошивки (CAN)
hdr2="$hdr2 $day $mounth $year $can_fw_version" # версия/дата
hdr2="$hdr2 $git_build" # Хеш коммита в репозитории git
len=$(printf "%08X" "$fw_size") # Len (Длина данных)
len=$(HexToByteString "$len")
hdr2="$hdr2 $len"
offset=$(printf "%08X" "$fw_start_addr") # offset (смещение прошивки во flash)
offset=$(HexToByteString "$offset")
hdr2="$hdr2 $offset"
rand=$(GetRandomByteString 8)
# echo "rand: $rand"
hdr2="$hdr2 $rand"
# printf "hdr2:\n%s\n" "$hdr2"
crc=$(CRC32_FromByteString "$hdr2 $fw_data")
# printf "crc:\n%s\n" "$crc"
fw="$hdr1 $crc $hdr2 $fw_data"
# printf "fw:\n%s\n" "$fw" | fold -w48
fw_path="$(dirname "$1")/$text_info.fw"
printf "Generate \033[0;32m%s\033[0m\n" "$fw_path"
ByteStringToAsciiHex 0 "$fw" | srec_cat - -ascii_hex -o "$fw_path" -binary

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

108
sys/info/install.md Normal file
View File

@@ -0,0 +1,108 @@
## Подготовка к работе
Предварительно должен быть установлен и настроен [Git for Windows 64-bit](https://git-scm.com/download/win).
Также должны быть установлены 64-bit драйверы J-Link в папку `C:/Program Files/SEGGER/JLink/`
* Update existing installation
* Install for all users
![alt text](JLink_drivers_install.png)
---
### Установка Dev Tools
Запускаем скрипт [sys/install.sh](../../sys/install.sh)
Произойдет скачивание и распаковка архивов с build tools и toolchain в папку `С:/xpack-dev-tools`. Никакие переменные среды не меняются, установка полностью независима (портативная) и не затрагивает никакие другие программы.
После установки Dev Tools необходимо перезапустить VSCode если он был запущен.
---
### Установка VSCode
Скачиваем и устанавливаем [стабильную версию](https://code.visualstudio.com/).
- Открываем папку с нашим проектом в VSCode.
- Открываем расширения `Ctrl+Shift+X`.
- Устанавливаем расширения рекомендованные нашим `workspace`. Они помечены текстом `This extension is recommended by users of the current workspace.`
- [C/C++](vscode:extension/ms-vscode.cpptools) и [Cortex-Debug](vscode:extension/marus25.cortex-debug) обязательны к установке, остальные по желанию.
Дополнительные расширения:
- [Git Graph](vscode:extension/mhutchie.git-graph) - рекомендую для работы с git.
- [LinkerScript](vscode:extension/ZixuanWang.linkerscript) - Linker Script files syntax.
- [GNU Linker Map files](vscode:extension/trond-snekvik.gnu-mapfiles) - Linker Map files syntax.
- [Intel HEX format](vscode:extension/keroc.hex-fmt) - Intel Hex files syntax.
- [Hex Editor](vscode:extension/ms-vscode.hexeditor) - Hex editor for binary files.
- [Arm Assembly](vscode:extension/dan-c-underwood.arm) - ARM Assembly files syntax.
- [Material Icon Theme](vscode:extension/pkief.material-icon-theme) - Симпатичные иконки файлов и папок в Explorer слева.
- [EditorConfig for VS Code](vscode:extension/EditorConfig.EditorConfig) - Следит за табами/пробелами/отступами/кодировкой для всех файлов проекта.
- [Open in External App](vscode:extension/YuTengjing.open-in-external-app) - Позволяет открывать файлы проекта в системных приложениях прямо из VSCode.
- [Task Buttons](vscode:extension/spencerwmiles.vscode-task-buttons) - Отображает кнопки для запуска тасков в статусбаре.
Рекомендации всех расширений находятся в файле [.vscode/extensions.json](../../.vscode/extensions.json).
---
### Сборка проекта в консоли
Сборка осуществяется с помощью `make`.
В папке `settings` находятся скрипты экспорта переменных окружения:
- [sys/export.sh](../../sys/export.sh) - для bash
- [sys/export.bat](../../sys/export.bat) - для cmd
- [sys/export.ps1](../../sys/export.ps1) - для powershell
Чтобы все наши компиляторы/линкеры/утилиты да и сам `make` стали доступными, вначале необходимо запустить соответствующий скрипт экспорта.
Для bash запускаем через точку `. sys/export.sh`. Для остальных достаточно просто запустить скрипт.
Далее просто запускаем нужный `make` таргет.
#### Команды `make`
- `make -e MODEL=M2 debug` - сборка дебага M2
- `make -e MODEL=M3 debug` - сборка дебага M3
- `make -e MODEL=M2 release` - сборка релиза M2
- `make -e MODEL=M3 release` - сборка релиза M3
Релизные сборки отличаются отключеным дефайном `DEBUG` и оптимизацией кода по размеру.
---
### Сборка проекта в консоли VSCode
Тут проще:
- Открываем папку с нашим проектом в VSCode.
- Открываем консоль `Ctrl+~`. (запустится терминал по молчанию)
- Можете выбрать свой любимый терминал. Я предпочитаю `Git Bash`.
- И сразу можем набирать команды `make`.
В файле [.vscode/settings.json](../../.vscode/settings.json) находятся конфигурации встроенных терминалов которые автоматически подгружают скрипты экспорта при открытии.
---
### Сборка проекта с помощью VSCode Tasks.
- Открываем папку с нашим проектом в VSCode.
- Нажимаем `Ctrl+Shift+B` и выбираем нужный Task.
Таски находятся в файле [.vscode/tasks.json](../../.vscode/tasks.json). Они автоматически загружают экспорт окружения и запускают нужные команды `make`.
Если установлено расширение [Task Buttons](vscode:extension/spencerwmiles.vscode-task-buttons), то в строке статуса появятся кнопки для удобного запуска тасков `M2 Release`, `M3 Release`, `M2 Debug`, `M3 Debug`, `Clean`.
---
### Отладка VSCode
В разделе `Run and Debug` слева выбираем конфигурацию отладки `Debug M2` или `Debug M3` и нажимаем зеленую стрелочку `Start Debugging` или `F5`.
Проект автоматически соберется (preLaunchTask), прошьется МК и запустится отладка.
Вывод логов доступен в терминале `SWO:ITM`.
В дальнейшем если конфигурация ранее уже была выбрана, то для запуска компиляции и отладки достаточно просто нажимать `F5`.
---
### PowerShell (если возникает ошибка)
В PowerShell по умолчанию отключено выполнение скриптов. Для исправления:
- Открываем PowerShell от имени администратора.
- Пишем и запускаем: `Set-ExecutionPolicy RemoteSigned`
- На вопрос отвечаем: A (Да для всех)
---

103
sys/install.sh Executable file
View File

@@ -0,0 +1,103 @@
#!/bin/sh
# shellcheck disable=SC2034
# This script installs dev tools (build tools & toolchain)
# https://github.com/xpack-dev-tools/windows-build-tools-xpack/releases
# https://github.com/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases
build_tools_version="4.4.1-2" # For Windows only
toolchain_version="12.3.1-1.2" # For all OS
###############################################################################################
install_path=~/.xpack-dev-tools # For all OS
api_build_tools_url=https://api.github.com/repos/xpack-dev-tools/windows-build-tools-xpack/releases
api_toolchain_url=https://api.github.com/repos/xpack-dev-tools/arm-none-eabi-gcc-xpack/releases
Extract() {
archive="$1"
if echo "$archive" | grep -E -- ".zip$" >/dev/null 2>&1; then
unzip -o "$archive"
fi
if echo "$archive" | grep -E -- ".tar.gz$" >/dev/null 2>&1; then
tar xvf "$archive"
fi
}
# Usage: Install [api_url] [version] [file_ending]
Install() {
api_url="$1"
version="$2"
file_ending="$3"
install_folder="xpack-"$(echo "$api_url" | cut -d '/' -f6 | sed "s/xpack/$version/")
# echo "Install folder: $install_folder"
if [ -d "$install_path/$install_folder" ]; then
echo "Use: $install_folder"
return
fi
url=$(curl --ssl-no-revoke -s -L "$api_url" | grep -- "browser_download_url" | grep -- "$version" | grep -- "$file_ending\"" | cut -d '"' -f4)
# echo "Download URL: $url"
archive=$(basename "$url")
# echo "Archive: $archive"
mkdir -p "$install_path"
cd "$install_path" || exit 1
curl --ssl-no-revoke -L -O "$url"
Extract "$archive"
rm "$archive"
}
# Windows
if uname | grep -- "MINGW64" >/dev/null 2>&1; then
Install "$api_build_tools_url" "$build_tools_version" "win32-x64.zip"
Install "$api_toolchain_url" "$toolchain_version" "win32-x64.zip"
exit
fi
# Linux
if uname | grep -- "Linux" >/dev/null 2>&1; then
if uname -a | grep -- "x86_64" >/dev/null 2>&1; then
Install "$api_toolchain_url" "$toolchain_version" "linux-x64.tar.gz"
elif uname -a | grep -- "aarch64" >/dev/null 2>&1; then
Install "$api_toolchain_url" "$toolchain_version" "linux-arm64.tar.gz"
elif uname -a | grep -- "arm" >/dev/null 2>&1; then
Install "$api_toolchain_url" "$toolchain_version" "linux-arm.tar.gz"
else
echo "Unknown Linux architecture"; exit 1
fi
if ( ! xxd --version > /dev/null 2>&1 ) || ( ! srec_cat --version > /dev/null 2>&1 ); then
sudo apt update
fi
if ! xxd --version > /dev/null 2>&1; then
sudo apt install -y xxd
else
echo "Use: xxd"
fi
if ! srec_cat --version > /dev/null 2>&1; then
sudo apt install -y srecord
else
echo "Use: srecord"
fi
exit
fi
# MAC
if uname | grep -- "Darwin" >/dev/null 2>&1; then
if uname -a | grep -- "arm64" >/dev/null 2>&1; then
Install "$api_toolchain_url" "$toolchain_version" "darwin-arm64.tar.gz"
elif uname -a | grep -- "x86_64" >/dev/null 2>&1; then
Install "$api_toolchain_url" "$toolchain_version" "darwin-x64.tar.gz"
else
echo "Unknown Darwin architecture"; exit 1
fi
brew install make srecord coreutils
exit
fi

Binary file not shown.

Binary file not shown.

BIN
sys/srecord/srec_cat.exe Normal file

Binary file not shown.

53
sys/version.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/bin/sh
# Скрипт генерирует версию сборки в файл version.h
OUTFILE=libs/Version.h
# rm $OUTFILE > /dev/null 2>&1
# echo -e "\033[0;32m~~~ Version generation ~~~\033[0m";
printf "version: "
if ! git --version > /dev/null 2>&1; then
printf "\n\033[0;31mGIT is not found!\033[0m\n"; exit 1;
fi
if ! git status > /dev/null 2>&1; then
printf "\n\033[0;31mThis is not a git repo!\033[0m\n"; exit 1;
fi
version=$(git describe --tags --always --dirty --abbrev=8 || echo unknown);
# Remove tag prefix from version
# Версия git в последнем поле после '_'
if echo "$version" | grep -q "_"; then
printf "%s => " "$version"
version=$(echo "$version" | awk -F '_' '{print $NF}')
fi
version=$(echo "$version" | sed "s/-g/-/") # Remove 'g' from git hash
echo "$version"
git_build="0x$(git rev-parse --short=8 HEAD | tr 'a-f' 'A-F')"
date="$(date +0x00%y%m%d)"
# Пишем в файл.
cat << --- > $OUTFILE
#ifndef __VERSION_H_
#define __VERSION_H_
// Данный файл обновляется автоматически из скрипта version.sh
// Хеш коммита в репозитории GIT.
#define GIT_BUILD $git_build
// Дата компиляции, YYMMDD, всё в bcd.
#define BUILD_DATE $date
// Версия CAN-прошивки.
#define CAN_FW_VERSION 1
// Версия из GIT.
#define GIT_VERSION "$version"
#endif /* __VERSION_H_ */
---

3
sys/zdotdir/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*
!.gitignore
!.zshrc

6
sys/zdotdir/.zshrc Normal file
View File

@@ -0,0 +1,6 @@
# This script should be sourced, not executed.
unset ZDOTDIR
. ~/.zshrc
. sys/export.zsh