textual
[RRG-proxmark3.git] / client / src / graph.c
blob5a9fb3b330c3de429015a89899cf44848224243a
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Graph utilities
9 //-----------------------------------------------------------------------------
10 #include "graph.h"
11 #include <stdlib.h>
12 #include <string.h>
13 #include "ui.h"
14 #include "proxgui.h"
15 #include "util.h" //param_get32ex
16 #include "lfdemod.h"
17 #include "cmddata.h" //for g_debugmode
20 int GraphBuffer[MAX_GRAPH_TRACE_LEN];
21 size_t GraphTraceLen;
23 /* write a manchester bit to the graph
24 TODO, verfy that this doesn't overflow buffer (iceman)
26 void AppendGraph(bool redraw, uint16_t clock, int bit) {
27 uint8_t half = clock / 2;
28 uint8_t i;
29 //set first half the clock bit (all 1's or 0's for a 0 or 1 bit)
30 for (i = 0; i < half; ++i)
31 GraphBuffer[GraphTraceLen++] = bit;
33 //set second half of the clock bit (all 0's or 1's for a 0 or 1 bit)
34 for (; i < clock; ++i)
35 GraphBuffer[GraphTraceLen++] = bit ^ 1;
37 if (redraw)
38 RepaintGraphWindow();
41 // clear out our graph window
42 size_t ClearGraph(bool redraw) {
43 size_t gtl = GraphTraceLen;
44 memset(GraphBuffer, 0x00, GraphTraceLen);
45 GraphTraceLen = 0;
46 if (redraw)
47 RepaintGraphWindow();
48 return gtl;
50 // option '1' to save GraphBuffer any other to restore
51 void save_restoreGB(uint8_t saveOpt) {
52 static int SavedGB[MAX_GRAPH_TRACE_LEN];
53 static size_t SavedGBlen = 0;
54 static bool GB_Saved = false;
55 static int SavedGridOffsetAdj = 0;
57 if (saveOpt == GRAPH_SAVE) { //save
58 memcpy(SavedGB, GraphBuffer, sizeof(GraphBuffer));
59 SavedGBlen = GraphTraceLen;
60 GB_Saved = true;
61 SavedGridOffsetAdj = GridOffset;
62 } else if (GB_Saved) { //restore
63 memcpy(GraphBuffer, SavedGB, sizeof(GraphBuffer));
64 GraphTraceLen = SavedGBlen;
65 GridOffset = SavedGridOffsetAdj;
66 RepaintGraphWindow();
70 void setGraphBuf(uint8_t *buff, size_t size) {
71 if (buff == NULL) return;
73 ClearGraph(false);
75 if (size > MAX_GRAPH_TRACE_LEN)
76 size = MAX_GRAPH_TRACE_LEN;
78 for (size_t i = 0; i < size; ++i)
79 GraphBuffer[i] = buff[i] - 128;
81 GraphTraceLen = size;
82 RepaintGraphWindow();
85 size_t getFromGraphBuf(uint8_t *buff) {
86 if (buff == NULL) return 0;
87 if (GraphTraceLen == 0) return 0;
89 size_t i;
90 for (i = 0; i < GraphTraceLen; ++i) {
91 //trim
92 if (GraphBuffer[i] > 127) GraphBuffer[i] = 127;
93 if (GraphBuffer[i] < -127) GraphBuffer[i] = -127;
94 buff[i] = (uint8_t)(GraphBuffer[i] + 128);
96 return i;
99 // A simple test to see if there is any data inside Graphbuffer.
100 bool HasGraphData(void) {
101 if (GraphTraceLen == 0) {
102 PrintAndLogEx(NORMAL, "No data available, try reading something first");
103 return false;
105 return true;
108 bool isGraphBitstream(void) {
109 // convert to bitstream if necessary
110 for (int i = 0; i < GraphTraceLen; i++) {
111 if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) {
112 return false;
115 return true;
118 void convertGraphFromBitstream(void) {
119 convertGraphFromBitstreamEx(1, 0);
122 void convertGraphFromBitstreamEx(int hi, int low) {
123 for (int i = 0; i < GraphTraceLen; i++) {
124 if (GraphBuffer[i] == hi)
125 GraphBuffer[i] = 127;
126 else if (GraphBuffer[i] == low)
127 GraphBuffer[i] = -127;
128 else
129 GraphBuffer[i] = 0;
132 uint8_t *bits = calloc(GraphTraceLen, sizeof(uint8_t));
133 if (bits == NULL) {
134 PrintAndLogEx(DEBUG, "ERR: convertGraphFromBitstreamEx, failed to allocate memory");
135 return;
138 size_t size = getFromGraphBuf(bits);
139 if (size == 0) {
140 PrintAndLogEx(WARNING, "Failed to copy from graphbuffer");
141 free(bits);
142 return;
145 // set signal properties low/high/mean/amplitude and is_noise detection
146 computeSignalProperties(bits, size);
147 free(bits);
148 RepaintGraphWindow();
151 // Get or auto-detect ask clock rate
152 int GetAskClock(const char *str, bool verbose) {
153 if (getSignalProperties()->isnoise)
154 return -1;
156 int clock1 = param_get32ex(str, 0, 0, 10);
157 if (clock1 > 0)
158 return clock1;
160 // Auto-detect clock
162 uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
163 if (bits == NULL) {
164 PrintAndLogEx(WARNING, "Failed to allocate memory");
165 return -1;
168 size_t size = getFromGraphBuf(bits);
169 if (size == 0) {
170 PrintAndLogEx(WARNING, "Failed to copy from graphbuffer");
171 free(bits);
172 return -1;
175 size_t ststart = 0, stend = 0;
176 bool st = DetectST(bits, &size, &clock1, &ststart, &stend);
177 int idx = stend;
178 if (st == false) {
179 idx = DetectASKClock(bits, size, &clock1, 20);
182 if (clock1 > 0) {
183 setClockGrid(clock1, idx);
185 // Only print this message if we're not looping something
186 if (verbose || g_debugMode)
187 PrintAndLogEx(SUCCESS, "Auto-detected clock rate: %d, Best Starting Position: %d", clock1, idx);
189 free(bits);
190 return clock1;
193 int GetPskCarrier(bool verbose) {
194 if (getSignalProperties()->isnoise)
195 return -1;
197 uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
198 if (bits == NULL) {
199 PrintAndLogEx(WARNING, "Failed to allocate memory");
200 return -1;
203 size_t size = getFromGraphBuf(bits);
204 if (size == 0) {
205 PrintAndLogEx(WARNING, "Failed to copy from graphbuffer");
206 free(bits);
207 return -1;
210 uint16_t fc = countFC(bits, size, false);
211 free(bits);
213 uint8_t carrier = fc & 0xFF;
214 if (carrier != 2 && carrier != 4 && carrier != 8) return 0;
215 if ((fc >> 8) == 10 && carrier == 8) return 0;
216 // Only print this message if we're not looping something
217 if (verbose)
218 PrintAndLogEx(SUCCESS, "Auto-detected PSK carrier rate: %d", carrier);
220 return carrier;
223 int GetPskClock(const char *str, bool verbose) {
225 if (getSignalProperties()->isnoise)
226 return -1;
228 int clock1 = param_get32ex(str, 0, 0, 10);
229 if (clock1 != 0)
230 return clock1;
232 // Auto-detect clock
233 uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
234 if (bits == NULL) {
235 PrintAndLogEx(WARNING, "Failed to allocate memory");
236 return -1;
239 size_t size = getFromGraphBuf(bits);
240 if (size == 0) {
241 PrintAndLogEx(WARNING, "Failed to copy from graphbuffer");
242 free(bits);
243 return -1;
246 size_t firstPhaseShiftLoc = 0;
247 uint8_t curPhase = 0, fc = 0;
248 clock1 = DetectPSKClock(bits, size, 0, &firstPhaseShiftLoc, &curPhase, &fc);
250 if (clock1 >= 0)
251 setClockGrid(clock1, firstPhaseShiftLoc);
253 // Only print this message if we're not looping something
254 if (verbose)
255 PrintAndLogEx(SUCCESS, "Auto-detected clock rate: %d", clock1);
257 free(bits);
258 return clock1;
261 int GetNrzClock(const char *str, bool verbose) {
263 if (getSignalProperties()->isnoise)
264 return -1;
266 int clock1 = param_get32ex(str, 0, 0, 10);
267 if (clock1 != 0)
268 return clock1;
270 // Auto-detect clock
271 uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
272 if (bits == NULL) {
273 PrintAndLogEx(WARNING, "Failed to allocate memory");
274 return -1;
277 size_t size = getFromGraphBuf(bits);
278 if (size == 0) {
279 PrintAndLogEx(WARNING, "Failed to copy from graphbuffer");
280 free(bits);
281 return -1;
284 size_t clkStartIdx = 0;
285 clock1 = DetectNRZClock(bits, size, 0, &clkStartIdx);
286 setClockGrid(clock1, clkStartIdx);
287 // Only print this message if we're not looping something
288 if (verbose)
289 PrintAndLogEx(SUCCESS, "Auto-detected clock rate: %d", clock1);
291 free(bits);
292 return clock1;
295 //by marshmellow
296 //attempt to detect the field clock and bit clock for FSK
297 int GetFskClock(const char *str, bool verbose) {
299 int clock1 = param_get32ex(str, 0, 0, 10);
300 if (clock1 != 0)
301 return clock1;
303 uint8_t fc1 = 0, fc2 = 0, rf1 = 0;
304 int firstClockEdge = 0;
306 if (fskClocks(&fc1, &fc2, &rf1, &firstClockEdge) == false)
307 return 0;
309 if ((fc1 == 10 && fc2 == 8) || (fc1 == 8 && fc2 == 5)) {
310 if (verbose)
311 PrintAndLogEx(SUCCESS, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1);
313 setClockGrid(rf1, firstClockEdge);
314 return rf1;
317 PrintAndLogEx(DEBUG, "DEBUG: unknown fsk field clock detected");
318 PrintAndLogEx(DEBUG, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1);
319 return 0;
322 bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge) {
324 if (getSignalProperties()->isnoise)
325 return false;
327 uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t));
328 if (bits == NULL) {
329 PrintAndLogEx(WARNING, "Failed to allocate memory");
330 return false;
333 size_t size = getFromGraphBuf(bits);
334 if (size == 0) {
335 PrintAndLogEx(WARNING, "Failed to copy from graphbuffer");
336 free(bits);
337 return false;
340 uint16_t ans = countFC(bits, size, true);
341 if (ans == 0) {
342 PrintAndLogEx(DEBUG, "DEBUG: No data found");
343 free(bits);
344 return false;
347 *fc1 = (ans >> 8) & 0xFF;
348 *fc2 = ans & 0xFF;
349 *rf1 = detectFSKClk(bits, size, *fc1, *fc2, firstClockEdge);
351 free(bits);
353 if (*rf1 == 0) {
354 PrintAndLogEx(DEBUG, "DEBUG: Clock detect error");
355 return false;
357 return true;