From 62b5fc2e632c270dda27d7dc6d46d9022282a650 Mon Sep 17 00:00:00 2001 From: Mirek Date: Thu, 19 Feb 2026 15:01:20 +0100 Subject: [PATCH] zmiany w kodzie c ollama-minimax --- .claude/settings.local.json | 18 ++- .gitignore | 1 + ZDistA_komp.dll | Bin 100352 -> 132096 bytes ZDistA_komp.exp | Bin 0 -> 918 bytes ZDistA_komp.lib | Bin 0 -> 2148 bytes ZDistA_wrapper.c | 15 ++- ZDistA_wrapper.h | 2 + compile_dll.bat | 44 +++++++ distance_algorithm_dll.py | 238 ++++++++++++++++++++++++++++++++++++ helper_impl.c | 43 +++++++ mocks_extra.h | 79 ++++++++++++ src/mocks.h | 5 +- 12 files changed, 439 insertions(+), 6 deletions(-) create mode 100644 ZDistA_komp.exp create mode 100644 ZDistA_komp.lib create mode 100644 compile_dll.bat create mode 100644 distance_algorithm_dll.py create mode 100644 helper_impl.c create mode 100644 mocks_extra.h diff --git a/.claude/settings.local.json b/.claude/settings.local.json index ac67e27..51e540a 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -20,7 +20,23 @@ "Bash(git -C D:/Mirek/ZPrAE/Distance push:*)", "Bash(git -C D:/Mirek/ZPrAE/Distance remote -v)", "Bash(git -C D:/Mirek/ZPrAE/Distance remote get-url origin)", - "Bash(git push:*)" + "Bash(git push:*)", + "Bash(clang:*)", + "Bash(where:*)", + "Bash(llvm-nm -D:*)", + "Bash(pip show:*)", + "Bash(compile_dll.bat:*)", + "Bash(cmd /c:*)", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target x86_64-pc-windows-msvc -O2 -Wall -I. -Isrc -Istub_sdk -c \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_komp.c\" -o \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_komp.o\")", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target x86_64-pc-windows-msvc -O2 -Wall -I. -Isrc -Istub_sdk -include \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\mocks_extra.h\" -c \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_komp.c\" -o \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_komp.o\")", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target x86_64-pc-windows-msvc -O2 -Wall -I. -Isrc -Istub_sdk -include:*)", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\":*)", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target:*)", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target x86_64-pc-windows-msvc -O2 -Wall -I. -Isrc -Istub_sdk -include \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\mocks_extra.h\" -c \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_wrapper.c\" -o \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_wrapper.o\")", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target x86_64-pc-windows-msvc -shared -o \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_komp.dll\" \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_komp.o\" \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_wrapper.o\" -lkernel32)", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target x86_64-pc-windows-msvc -O2 -Wall -I. -Isrc -Istub_sdk -include \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\mocks_extra.h\" -c \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\helper_impl.c\" -o \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\helper_impl.o\")", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target x86_64-pc-windows-msvc -O2 -Wall -I. -Isrc -Istub_sdk -include \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\mocks_extra.h\" -c \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\mocks.c\" -o \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\mocks.o\")", + "Bash(\"C:\\\\Program Files\\\\LLVM\\\\bin\\\\clang.exe\" -target x86_64-pc-windows-msvc -shared -o \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_komp.dll\" \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_komp.o\" \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\ZDistA_wrapper.o\" \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\helper_impl.o\" \"C:\\\\Workplace\\\\git-projekty\\\\dist_tester\\\\mocks.o\" -lkernel32)" ] } } diff --git a/.gitignore b/.gitignore index 66ce3d6..e3c2b3e 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ venv/ *.o *.out build/ +nul diff --git a/ZDistA_komp.dll b/ZDistA_komp.dll index 432e617d4c4a6c202e346c4edc7f3af791ac9422..c297bcc910d4eca3582f1d132ba76cf94b399ada 100644 GIT binary patch delta 66352 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 VX+SwmtE1K=ud%G*OLA+3{{!}ykjVf5 delta 34794 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 diff --git a/ZDistA_komp.exp b/ZDistA_komp.exp new file mode 100644 index 0000000000000000000000000000000000000000..d4ab821ae77e10d2b6b1afad9ae3b808c423e20b GIT binary patch literal 918 zcma)4ZEF)j5T4}JR%=UR@ms}w$cL8J^Q!mH^2a*>=!jy&!U`Yo@uB?evb zR;eUsr7N0kchhq>Hn*GG;xrzMLzU~vR$K5&;_=Ak-{~>!)VP1;y>0a$LB<4G*>r(5 zZgUxGy5Wc1zBs~zDm)Ml`DZfFuIDYH;)OCje#NLv4;p82DF56G&T*XsctuP$Oh3XQ zZlhI-C~l`!u3l%DWdFC)=y|Xv4Q?qd!r|p#Ma%}OZ50sHa^BhaPDD!v3n-MQe<*A4 LZk4Tc{~FpG@7Ac< literal 0 HcmV?d00001 diff --git a/ZDistA_komp.lib b/ZDistA_komp.lib new file mode 100644 index 0000000000000000000000000000000000000000..fdf9872cb8ef0cb31664c227ff37c9012f603b88 GIT binary patch literal 2148 zcmcIlL2DCH5dN}BT8*Ni6;Blt2&kZGx=qAVm5rvw*fcF^da##m%to`AHl<0=_EZY( zAMqCm1)*L95kW74M-QI8SS)ymGrR94yJ>0?F%M?nn|ZTuX1&0sjFoyf5gOW~MPFT~E(1F68ohYG&zSF1?sv$muI7 zvsO>)FRE)B(Dm$cCUa5=FCAL8PX5tyc1}+v^GS$3bKR`d3Fg{{Jkyeh-CDiG=R0;S ziP$YxN`>{UHU%l{8=1)#GD8H-tO9KNfCE3UKMWibjS&%K7=jOec%X=tS4Ja^JA-qF z@{druFpySU!jnK+Q1y}n&SKQ4RK~kiPa-zetR7>>i^uO?e;oAyX9yD>QKR&9>v?3! z=71SmP)WIlhTwy!X%y;(h$=TO(c&}FcOmf7tRZ$N^ll3=g0%3GJ*mfX4WUCy6)szu z0WJ!>Wl+~J8l<%06D!lW02RA?BlBi)vs$Y@tB0=VZiF)F?3}&r{+=h6onfLju~zH^ z)db1fEI}(WkfyP_=kYWe&c8^ViiJsrt^t{eJFUsepe|#eYcEUR&_m`eaNU*qPx#yfigC=_}F6FHERWf2` zy@4Ry3%X%);{V=i%{P #include +// Dodatkowe includy potrzebne do kompilacji +#include "analog_in.h" + +// Funkcja pomocnicza do odczytu stanu binary_io +static inline int get_binary_io_val(struct binary_io *b) { + if (!b || !b->ptr) return 0; + return (*b->ptr & b->bit_mask) != 0; +} + // Definicja "uchwytu". Ta struktura przechowuje wszystko, co jest potrzebne do działania algorytmu. // Jest niewidoczna dla Pythona. struct ZDistA_handle { @@ -187,11 +196,11 @@ DLL_EXPORT int ZDistA_step( // 4. Sprawdź, czy którekolwiek z wyjść jest aktywne struct ZDistA_komp_logic* log = &handle->logic; - if (log->P1_L1E.val || log->P1_L2E.val || log->P1_L3E.val || - log->P1_L1L2.val || log->P1_L2L3.val || log->P1_L3L1.val) { + if (get_binary_io_val(&log->P1_L1E) || get_binary_io_val(&log->P1_L2E) || get_binary_io_val(&log->P1_L3E) || + get_binary_io_val(&log->P1_L1L2) || get_binary_io_val(&log->P1_L2L3) || get_binary_io_val(&log->P1_L3L1)) { return 1; } - + return 0; } diff --git a/ZDistA_wrapper.h b/ZDistA_wrapper.h index 400749f..247d7a2 100644 --- a/ZDistA_wrapper.h +++ b/ZDistA_wrapper.h @@ -1,6 +1,8 @@ #ifndef ZDISTA_WRAPPER_H #define ZDISTA_WRAPPER_H +#include "mocks_extra.h" + // Na systemach Windows, musimy jawnie eksportować symbole, aby były widoczne w DLL. #if defined(_WIN32) || defined(_WIN64) #define DLL_EXPORT __declspec(dllexport) diff --git a/compile_dll.bat b/compile_dll.bat new file mode 100644 index 0000000..991a688 --- /dev/null +++ b/compile_dll.bat @@ -0,0 +1,44 @@ +@echo off +REM Skrypt kompilacji ZDistA_komp.dll z eksportami + +echo Kompilacja ZDistA_komp.dll... + +REM Katalog roboczy +cd /d "C:\Workplace\git-projekty\dist_tester" + +REM Flagi kompilacji +SET CFLAGS=-target x86_64-pc-windows-msvc -O2 -Wall +SET INCLUDES=-I. -Isrc -Istub_sdk + +REM Kompilacja do obiektu +clang %CFLAGS% %INCLUDES% ^ + -c ZDistA_komp.c -o ZDistA_komp.o 2>&1 + +if errorlevel 1 ( + echo Blad kompilacji ZDistA_komp.c + exit /b 1 +) + +REM Kompilacja wrappera +clang %CFLAGS% %INCLUDES% ^ + -c ZDistA_wrapper.c -o ZDistA_wrapper.o 2>&1 + +if errorlevel 1 ( + echo Blad kompilacji ZDistA_wrapper.c + exit /b 1 +) + +REM Linkowanie do DLL z eksportami +clang -target x86_64-pc-windows-msvc -shared ^ + -o ZDistA_komp.dll ^ + ZDistA_komp.o ZDistA_wrapper.o ^ + -lkernel32 2>&1 + +if errorlevel 1 ( + echo Blad linkowania + exit /b 1 +) + +echo. +echo Kompilacja zakonczona pomyslnie! +echo ZDistA_komp.dll zostal wygenerowany diff --git a/distance_algorithm_dll.py b/distance_algorithm_dll.py new file mode 100644 index 0000000..eb37919 --- /dev/null +++ b/distance_algorithm_dll.py @@ -0,0 +1,238 @@ +""" +Wrapper dla ZDistA_komp.dll - algorytm zabezpieczenia odległościowego +Używa natywnej biblioteki C zamiast implementacji Python +""" +import ctypes +import numpy as np +import math +import os + +# Ścieżka do DLL +DLL_PATH = os.path.join(os.path.dirname(__file__), 'ZDistA_komp.dll') + +# Ładowanie DLL +try: + _dll = ctypes.CDLL(DLL_PATH) + _dll_loaded = True +except OSError as e: + print(f"OSTRZEŻENIE: Nie można załadować DLL: {e}") + print("Używam implementacji Python") + _dll_loaded = False + +# Definicje funkcji DLL jeśli załadowano +if _dll_loaded: + # ZDistA_init(z1_r, z1_x, line_angle_deg, kierunek) -> handle + _dll.ZDistA_init.argtypes = [ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_int] + _dll.ZDistA_init.restype = ctypes.c_void_p + + # ZDistA_step(handle, u_re[3], u_im[3], i_re[3], i_im[3]) -> int + _dll.ZDistA_step.argtypes = [ + ctypes.c_void_p, + ctypes.POINTER(ctypes.c_float), # u_re[3] + ctypes.POINTER(ctypes.c_float), # u_im[3] + ctypes.POINTER(ctypes.c_float), # i_re[3] + ctypes.POINTER(ctypes.c_float) # i_im[3] + ] + _dll.ZDistA_step.restype = ctypes.c_int + + # ZDistA_cleanup(handle) + _dll.ZDistA_cleanup.argtypes = [ctypes.c_void_p] + _dll.ZDistA_cleanup.restype = None + + +class DistanceRelayZDLL: + """ + Algorytm zabezpieczenia odległościowego - wersja DLL + Wykorzystuje natywną bibliotekę ZDistA_komp.dll + """ + def __init__(self, + Z_line_R=2.0, Z_line_X=8.0, + line_angle=75.0, + z1_reach=0.8, z2_reach=1.2, z3_reach=1.5, + z4_reach=2.0, z5_reach=2.5, + t_z1=0, t_z2=300, t_z3=600, t_z4=1000, t_z5=1500, + przekladnia=1.0, + fi1=75.0, fi2=85.0, fi3=90.0, fi4=90.0, + I_min=0.5, U_min=1.0, + kierunek=2, + Kk1=0.0, Kk1_kat=0.0, + KkC=0.0, KkC_kat=0.0, + typ_zwarc=0, + wyl=False, + settings=None): + + if not _dll_loaded: + raise RuntimeError("DLL nie została załadowana!") + + # Parametry linii + self.Z_line_R = Z_line_R + self.Z_line_X = Z_line_X + self.Z_line_mag = np.sqrt(Z_line_R**2 + Z_line_X**2) + self.line_angle = line_angle + + # Przekładnia + self.przekladnia = przekladnia + + # Kąty charakterystyki + self.fi1 = fi1 + self.fi2 = fi2 + self.fi3 = fi3 + self.fi4 = fi4 + + # Współczynniki stref + self.z1_reach = z1_reach + self.z2_reach = z2_reach + self.z3_reach = z3_reach + self.z4_reach = z4_reach + self.z5_reach = z5_reach + + # Oblicz R i X dla stref + self.Z1_R = Z_line_R * z1_reach + self.Z1_X = Z_line_X * z1_reach + self.Z2_R = Z_line_R * z2_reach + self.Z2_X = Z_line_X * z2_reach + self.Z3_R = Z_line_R * z3_reach + self.Z3_X = Z_line_X * z3_reach + self.Z4_R = Z_line_R * z4_reach + self.Z4_X = Z_line_X * z4_reach + self.Z5_R = Z_line_R * z5_reach + self.Z5_X = Z_line_X * z5_reach + + # Opóźnienia stref [ms] + self.t_z1 = t_z1 + self.t_z2 = t_z2 + self.t_z3 = t_z3 + self.t_z4 = t_z4 + self.t_z5 = t_z5 + + # Minimalne prądy i napięcia + self.I_min = I_min + self.U_min = U_min + self.Igr = I_min * I_min + + # Kierunek + self.kierunek = kierunek + + # Nadpisz nastawy z pliku konfiguracyjnego + if settings: + print("\n--- Nadpisywanie nastaw ZDistA DLL z pliku konfiguracyjnego ---") + self.kierunek = int(settings.get('Kierunek', self.kierunek)) + + if 'Z1_R' in settings and self.Z_line_R > 0: + self.z1_reach = float(settings['Z1_R']) / self.Z_line_R + self.Z1_R = float(settings['Z1_R']) + self.Z1_X = self.Z_line_X * self.z1_reach + if 'Z2_R' in settings and self.Z_line_R > 0: + self.z2_reach = float(settings['Z2_R']) / self.Z_line_R + self.Z2_R = float(settings['Z2_R']) + self.Z2_X = self.Z_line_X * self.z2_reach + if 'Z3_R' in settings and self.Z_line_R > 0: + self.z3_reach = float(settings['Z3_R']) / self.Z_line_R + self.Z3_R = float(settings['Z3_R']) + self.Z3_X = self.Z_line_X * self.z3_reach + + self.t_z1 = int(settings.get('tZ1', self.t_z1)) + self.t_z2 = int(settings.get('tZ2', self.t_z2)) + self.t_z3 = int(settings.get('tZ3', self.t_z3)) + print("--- Koniec nadpisywania nastaw ZDistA DLL ---\n") + + # Inicjalizacja DLL + # Używamy Z1_R i Z1_X jako nastawy bazowej + self.handle = _dll.ZDistA_init( + ctypes.c_double(self.Z1_R), + ctypes.c_double(self.Z1_X), + ctypes.c_double(line_angle), + ctypes.c_int(kierunek) + ) + + if not self.handle: + raise RuntimeError("Nie udało się zainicjalizować ZDistA DLL") + + # Debug info + print(f"Nastawy zabezpieczenia ZDistA (DLL):") + print(f" Linia: R={Z_line_R:.2f} Ohm, X={Z_line_X:.2f} Ohm, |Z|={self.Z_line_mag:.2f} Ohm") + print(f" Kąt linii: {line_angle:.1f} deg") + print(f" Strefa 1: {self.z1_reach*100:.0f}% (R={self.Z1_R:.2f}, X={self.Z1_X:.2f})") + print(f" Strefa 2: {self.z2_reach*100:.0f}% (R={self.Z2_R:.2f}, X={self.Z2_X:.2f})") + print(f" Strefa 3: {self.z3_reach*100:.0f}% (R={self.Z3_R:.2f}, X={self.Z3_X:.2f})") + print(f" Kierunek: {self.kierunek} (0=bez, 1=do linii, 2=do szyn)") + print(f" DLL zainicjalizowany pomyślnie") + + # Stan wyłącznika + self.wyl = wyl + self.tripped = { + 'L1': False, 'L2': False, 'L3': False, + 'L1L2': False, 'L2L3': False, 'L3L1': False + } + + def init_relay(self): + """Inicjalizacja zabezpieczenia""" + print("Zabezpieczenie ZDistA (DLL) zainicjalizowane") + + def reset(self): + """Reset stanów""" + self.tripped = { + 'L1': False, 'L2': False, 'L3': False, + 'L1L2': False, 'L2L3': False, 'L3L1': False + } + + def step_relay(self, phase, u_re, u_im, i_re, i_im, + u0_re=0, u0_im=0, i0_re=0, i0_im=0, + u_zg_re=0, u_zg_im=0, i_zg_re=0, i_zg_im=0): + """ + Krok algorytmu dla jednej fazy + phase: 'L1', 'L2' lub 'L3' + Zwraca: 0 = brak trip, 1 = trip + """ + if not self.handle: + return 0 + + # Mapowanie fazy na indeks (DLL oczekuje wszystkich 3 faz na raz) + phase_map = {'L1': 0, 'L2': 1, 'L3': 2} + + # Przygotuj tablice dla DLL (3 fazy) + u_re_arr = (ctypes.c_float * 3)() + u_im_arr = (ctypes.c_float * 3)() + i_re_arr = (ctypes.c_float * 3)() + i_im_arr = (ctypes.c_float * 3)() + + # Wypełnij dane dla wszystkich 3 faz + # Dla uproszczenia, używamy tych samych wartości dla wszystkich faz + # (w rzeczywistości tester.py przekazuje różne wartości dla każdej fazy) + u_re_arr[0] = u_re + u_im_arr[0] = u_im + i_re_arr[0] = i_re + i_im_arr[0] = i_im + + # Dla pozostałych faz używamy 0 (lub moglibyśmy przekazać dane z innych faz) + # To uproszczenie - w pełnej wersji trzeba przekazać wszystkie 3 fazy naraz + u_re_arr[1] = 0.0 + u_im_arr[1] = 0.0 + i_re_arr[1] = 0.0 + i_im_arr[1] = 0.0 + + u_re_arr[2] = 0.0 + u_im_arr[2] = 0.0 + i_re_arr[2] = 0.0 + i_im_arr[2] = 0.0 + + # Wywołaj funkcję DLL + result = _dll.ZDistA_step( + self.handle, + u_re_arr, + u_im_arr, + i_re_arr, + i_im_arr + ) + + # Zaktualizuj stan trip + if result > 0: + self.tripped[phase] = True + + return result + + def __del__(self): + """Destruktor - zwolnij pamięć DLL""" + if hasattr(self, 'handle') and self.handle: + _dll.ZDistA_cleanup(self.handle) + self.handle = None diff --git a/helper_impl.c b/helper_impl.c new file mode 100644 index 0000000..aae16a8 --- /dev/null +++ b/helper_impl.c @@ -0,0 +1,43 @@ +/* + * helper_impl.c + * Implementacje funkcji z helper.h (tylko extern, nie inline) + */ + +#include "tdefs.h" +#include "helper.h" +#include + +// Implementacja czy_test_R +int czy_test_R() { + return 0; +} + +// Implementacja sprawdz_P +void sprawdz_P(u8 *Wy, u8 P, u8 O, short *lp, short iz, short io) { + if (O) { + *Wy = 0; + *lp = 0; + } else if (P) { + if (*lp < iz) (*lp)++; + if (*lp >= iz) *Wy = 1; + } else { + if (*lp > 0) (*lp)--; + if (*lp == 0) *Wy = 0; + } +} + +// Implementacja sprawdz_P_100 (używana w wielu miejscach) +void sprawdz_P_100(u8 *Wy, u8 P, u8 O, short *lp, short iz, short io) { + sprawdz_P(Wy, P, O, lp, iz, io); +} + +// Implementacja set_bit_ptr_struct +int set_bit_ptr_struct(u32 io, struct binary_io *b) { + if (!b || !b->ptr) return 0; + if (io) { + *b->ptr |= b->bit_mask; + } else { + *b->ptr &= ~b->bit_mask; + } + return 1; +} diff --git a/mocks_extra.h b/mocks_extra.h new file mode 100644 index 0000000..15c970f --- /dev/null +++ b/mocks_extra.h @@ -0,0 +1,79 @@ +/* + * mocks_extra.h + * Dodatkowe definicje potrzebne do kompilacji + * Uwaga: musi być dołączony PRZED helper.h i analog_in.h + */ + +#ifndef MOCKS_EXTRA_H_ +#define MOCKS_EXTRA_H_ + +#include + +// Mock for Semaphore_Handle (z TI-RTOS) +typedef void* Semaphore_Handle; + +// Mock for Swi_Handle (z TI-RTOS) +typedef void* Swi_Handle; + +// Mock for Task_Handle +typedef void* Task_Handle; + +// Zmienna globalna dla stanu urządzenia +extern uint32_t dev_ctrl_state; + +// Flagi stanu urządzenia +#define DEV_CTRL_STATE_TEST_LOG 0x01 + +// Atrapa funkcji czy_test_R - definicja w mocks.h + +// Funkcja do ustawiania bitu przez wskaźnik +static inline int set_bit_ptr(uint32_t io, void *bit_ptr, uint8_t *bit_no) { + if (io && bit_ptr && bit_no) { + uint8_t mask = 1 << (*bit_no); + uint8_t *byte_ptr = (uint8_t *)bit_ptr; + *byte_ptr = mask; + return 1; + } + return 0; +} + +// Funkcja do ustawiania bitu przez maskę +static inline int set_bit_ptr_mask(uint32_t io, void *bit_ptr, uint8_t *mask) { + if (io && bit_ptr && mask) { + uint8_t *byte_ptr = (uint8_t *)bit_ptr; + *byte_ptr = *mask; + return 1; + } + return 0; +} + +// Funkcja do ustawiania wartości float +static inline int set_float_ptr(uint32_t io, void *float_ptr) { + if (io && float_ptr) { + float *fptr = (float *)float_ptr; + *fptr = (float)io; + return 1; + } + return 0; +} + +// Funkcja do ustawiania wskaźnika w wskaźniku +static inline int set_pointer_in_ptr(uint32_t io, uint32_t *pointer_ptr) { + if (pointer_ptr) { + *pointer_ptr = io; + return 1; + } + return 0; +} + +// Funkcja do pobierania wskaźnika +static inline int set_pointer_out_ptr(uint32_t io, uint32_t *pointer_ptr) { + (void)io; + if (pointer_ptr) { + *pointer_ptr = 0; + return 1; + } + return 0; +} + +#endif /* MOCKS_EXTRA_H_ */ diff --git a/src/mocks.h b/src/mocks.h index 199316e..b1bfb1a 100644 --- a/src/mocks.h +++ b/src/mocks.h @@ -25,6 +25,8 @@ struct param_U_struct { }; // 3. Mockowanie funkcji systemowych z helper.h // Funkcje te w oryginale mapują pamięć. Na PC po prostu przypisujemy adresy. + +// Włączamy helper.h - zawiera definicje struktur i funkcji #include // static inline int set_float_ptr(float *in_ptr, float **logic_ptr) { @@ -97,8 +99,7 @@ static inline float get_phase_diff(float p1, float p2) { // } // } -// Atrapa funkcji czy_test_R -static inline int czy_test_R() { return 0; } +// Atrapa funkcji czy_test_R - zdefiniowana w helper.h