| 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 | |
| 11 | #include <stdio.h> |
| 12 | #include <stdbool.h> |
| 13 | #include <string.h> |
| 14 | #include "ui.h" |
| 15 | #include "graph.h" |
| 16 | #include "lfdemod.h" |
| 17 | |
| 18 | int GraphBuffer[MAX_GRAPH_TRACE_LEN]; |
| 19 | int GraphTraceLen; |
| 20 | /* write a manchester bit to the graph */ |
| 21 | void AppendGraph(int redraw, int clock, int bit) |
| 22 | { |
| 23 | int i; |
| 24 | //set first half the clock bit (all 1's or 0's for a 0 or 1 bit) |
| 25 | for (i = 0; i < (int)(clock / 2); ++i) |
| 26 | GraphBuffer[GraphTraceLen++] = bit ; |
| 27 | //set second half of the clock bit (all 0's or 1's for a 0 or 1 bit) |
| 28 | for (i = (int)(clock / 2); i < clock; ++i) |
| 29 | GraphBuffer[GraphTraceLen++] = bit ^ 1; |
| 30 | |
| 31 | if (redraw) |
| 32 | RepaintGraphWindow(); |
| 33 | } |
| 34 | |
| 35 | // clear out our graph window |
| 36 | int ClearGraph(int redraw) |
| 37 | { |
| 38 | int gtl = GraphTraceLen; |
| 39 | memset(GraphBuffer, 0x00, GraphTraceLen); |
| 40 | |
| 41 | GraphTraceLen = 0; |
| 42 | |
| 43 | if (redraw) |
| 44 | RepaintGraphWindow(); |
| 45 | |
| 46 | return gtl; |
| 47 | } |
| 48 | // option '1' to save GraphBuffer any other to restore |
| 49 | void save_restoreGB(uint8_t saveOpt) |
| 50 | { |
| 51 | static int SavedGB[MAX_GRAPH_TRACE_LEN]; |
| 52 | static int SavedGBlen; |
| 53 | static bool GB_Saved = false; |
| 54 | |
| 55 | if (saveOpt==1) { //save |
| 56 | memcpy(SavedGB, GraphBuffer, sizeof(GraphBuffer)); |
| 57 | SavedGBlen = GraphTraceLen; |
| 58 | GB_Saved=true; |
| 59 | } else if (GB_Saved){ //restore |
| 60 | memcpy(GraphBuffer, SavedGB, sizeof(GraphBuffer)); |
| 61 | GraphTraceLen = SavedGBlen; |
| 62 | RepaintGraphWindow(); |
| 63 | } |
| 64 | return; |
| 65 | } |
| 66 | |
| 67 | // DETECT CLOCK NOW IN LFDEMOD.C |
| 68 | |
| 69 | void setGraphBuf(uint8_t *buff, size_t size) |
| 70 | { |
| 71 | if ( buff == NULL ) return; |
| 72 | |
| 73 | uint16_t i = 0; |
| 74 | if ( size > MAX_GRAPH_TRACE_LEN ) |
| 75 | size = MAX_GRAPH_TRACE_LEN; |
| 76 | ClearGraph(0); |
| 77 | for (; i < size; ++i){ |
| 78 | GraphBuffer[i]=buff[i]-128; |
| 79 | } |
| 80 | GraphTraceLen=size; |
| 81 | RepaintGraphWindow(); |
| 82 | return; |
| 83 | } |
| 84 | size_t getFromGraphBuf(uint8_t *buff) |
| 85 | { |
| 86 | if (buff == NULL ) return 0; |
| 87 | uint32_t i; |
| 88 | for (i=0;i<GraphTraceLen;++i){ |
| 89 | if (GraphBuffer[i]>127) GraphBuffer[i]=127; //trim |
| 90 | if (GraphBuffer[i]<-127) GraphBuffer[i]=-127; //trim |
| 91 | buff[i]=(uint8_t)(GraphBuffer[i]+128); |
| 92 | } |
| 93 | return i; |
| 94 | } |
| 95 | |
| 96 | // A simple test to see if there is any data inside Graphbuffer. |
| 97 | bool HasGraphData(){ |
| 98 | |
| 99 | if ( GraphTraceLen <= 0) { |
| 100 | PrintAndLog("No data available, try reading something first"); |
| 101 | return false; |
| 102 | } |
| 103 | return true; |
| 104 | } |
| 105 | |
| 106 | // Detect high and lows in Grapbuffer. |
| 107 | // Only loops the first 256 values. |
| 108 | void DetectHighLowInGraph(int *high, int *low, bool addFuzz) { |
| 109 | |
| 110 | uint8_t loopMax = 255; |
| 111 | if ( loopMax > GraphTraceLen) |
| 112 | loopMax = GraphTraceLen; |
| 113 | |
| 114 | for (uint8_t i = 0; i < loopMax; ++i) { |
| 115 | if (GraphBuffer[i] > *high) |
| 116 | *high = GraphBuffer[i]; |
| 117 | else if (GraphBuffer[i] < *low) |
| 118 | *low = GraphBuffer[i]; |
| 119 | } |
| 120 | |
| 121 | //12% fuzz in case highs and lows aren't clipped |
| 122 | if (addFuzz) { |
| 123 | *high = (int)(*high * .88); |
| 124 | *low = (int)(*low * .88); |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | // Get or auto-detect ask clock rate |
| 129 | int GetAskClock(const char str[], bool printAns, bool verbose) |
| 130 | { |
| 131 | int clock; |
| 132 | sscanf(str, "%i", &clock); |
| 133 | if (!strcmp(str, "")) |
| 134 | clock = 0; |
| 135 | |
| 136 | if (clock != 0) |
| 137 | return clock; |
| 138 | // Auto-detect clock |
| 139 | uint8_t grph[MAX_GRAPH_TRACE_LEN]={0}; |
| 140 | size_t size = getFromGraphBuf(grph); |
| 141 | if (size == 0) { |
| 142 | if (verbose) |
| 143 | PrintAndLog("Failed to copy from graphbuffer"); |
| 144 | return -1; |
| 145 | } |
| 146 | bool st = DetectST(grph, &size, &clock); |
| 147 | int start = 0; |
| 148 | if (st == false) { |
| 149 | start = DetectASKClock(grph, size, &clock, 20); |
| 150 | } |
| 151 | // Only print this message if we're not looping something |
| 152 | if (printAns){ |
| 153 | PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start); |
| 154 | } |
| 155 | return clock; |
| 156 | } |
| 157 | |
| 158 | uint8_t GetPskCarrier(const char str[], bool printAns, bool verbose) |
| 159 | { |
| 160 | uint8_t carrier=0; |
| 161 | uint8_t grph[MAX_GRAPH_TRACE_LEN]={0}; |
| 162 | size_t size = getFromGraphBuf(grph); |
| 163 | if ( size == 0 ) { |
| 164 | if (verbose) |
| 165 | PrintAndLog("Failed to copy from graphbuffer"); |
| 166 | return 0; |
| 167 | } |
| 168 | //uint8_t countPSK_FC(uint8_t *BitStream, size_t size) |
| 169 | |
| 170 | carrier = countFC(grph,size,0); |
| 171 | // Only print this message if we're not looping something |
| 172 | if (printAns){ |
| 173 | PrintAndLog("Auto-detected PSK carrier rate: %d", carrier); |
| 174 | } |
| 175 | return carrier; |
| 176 | } |
| 177 | |
| 178 | int GetPskClock(const char str[], bool printAns, bool verbose) |
| 179 | { |
| 180 | int clock; |
| 181 | sscanf(str, "%i", &clock); |
| 182 | if (!strcmp(str, "")) |
| 183 | clock = 0; |
| 184 | |
| 185 | if (clock!=0) |
| 186 | return clock; |
| 187 | // Auto-detect clock |
| 188 | uint8_t grph[MAX_GRAPH_TRACE_LEN]={0}; |
| 189 | size_t size = getFromGraphBuf(grph); |
| 190 | if ( size == 0 ) { |
| 191 | if (verbose) |
| 192 | PrintAndLog("Failed to copy from graphbuffer"); |
| 193 | return -1; |
| 194 | } |
| 195 | clock = DetectPSKClock(grph,size,0); |
| 196 | // Only print this message if we're not looping something |
| 197 | if (printAns){ |
| 198 | PrintAndLog("Auto-detected clock rate: %d", clock); |
| 199 | } |
| 200 | return clock; |
| 201 | } |
| 202 | |
| 203 | uint8_t GetNrzClock(const char str[], bool printAns, bool verbose) |
| 204 | { |
| 205 | int clock; |
| 206 | sscanf(str, "%i", &clock); |
| 207 | if (!strcmp(str, "")) |
| 208 | clock = 0; |
| 209 | |
| 210 | if (clock!=0) |
| 211 | return clock; |
| 212 | // Auto-detect clock |
| 213 | uint8_t grph[MAX_GRAPH_TRACE_LEN]={0}; |
| 214 | size_t size = getFromGraphBuf(grph); |
| 215 | if ( size == 0 ) { |
| 216 | if (verbose) |
| 217 | PrintAndLog("Failed to copy from graphbuffer"); |
| 218 | return -1; |
| 219 | } |
| 220 | clock = DetectNRZClock(grph, size, 0); |
| 221 | // Only print this message if we're not looping something |
| 222 | if (printAns){ |
| 223 | PrintAndLog("Auto-detected clock rate: %d", clock); |
| 224 | } |
| 225 | return clock; |
| 226 | } |
| 227 | //by marshmellow |
| 228 | //attempt to detect the field clock and bit clock for FSK |
| 229 | uint8_t GetFskClock(const char str[], bool printAns, bool verbose) |
| 230 | { |
| 231 | int clock; |
| 232 | sscanf(str, "%i", &clock); |
| 233 | if (!strcmp(str, "")) |
| 234 | clock = 0; |
| 235 | if (clock != 0) return (uint8_t)clock; |
| 236 | |
| 237 | |
| 238 | uint8_t fc1=0, fc2=0, rf1=0; |
| 239 | uint8_t ans = fskClocks(&fc1, &fc2, &rf1, verbose); |
| 240 | if (ans == 0) return 0; |
| 241 | if ((fc1==10 && fc2==8) || (fc1==8 && fc2==5)){ |
| 242 | if (printAns) PrintAndLog("Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); |
| 243 | return rf1; |
| 244 | } |
| 245 | if (verbose){ |
| 246 | PrintAndLog("DEBUG: unknown fsk field clock detected"); |
| 247 | PrintAndLog("Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); |
| 248 | } |
| 249 | return 0; |
| 250 | } |
| 251 | uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose) |
| 252 | { |
| 253 | uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; |
| 254 | size_t size = getFromGraphBuf(BitStream); |
| 255 | if (size==0) return 0; |
| 256 | uint16_t ans = countFC(BitStream, size, 1); |
| 257 | if (ans==0) { |
| 258 | if (verbose) PrintAndLog("DEBUG: No data found"); |
| 259 | return 0; |
| 260 | } |
| 261 | *fc1 = (ans >> 8) & 0xFF; |
| 262 | *fc2 = ans & 0xFF; |
| 263 | |
| 264 | *rf1 = detectFSKClk(BitStream, size, *fc1, *fc2); |
| 265 | if (*rf1==0) { |
| 266 | if (verbose) PrintAndLog("DEBUG: Clock detect error"); |
| 267 | return 0; |
| 268 | } |
| 269 | return 1; |
| 270 | } |