Merge pull request #1331 from Guilhem7/master
[RRG-proxmark3.git] / armsrc / util.c
blob443c9e5f4d780dba082e5e6088f7b15341c53fa6
1 //-----------------------------------------------------------------------------
2 // Jonathan Westhues, Sept 2005
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 // Utility functions used in many places, not specific to any piece of code.
9 //-----------------------------------------------------------------------------
10 #include "util.h"
12 #include "proxmark3_arm.h"
13 #include "ticks.h"
14 #include "commonutil.h"
15 #include "dbprint.h"
16 #include "string.h"
17 #include "usb_cdc.h"
18 #include "usart.h"
20 size_t nbytes(size_t nbits) {
21 return (nbits >> 3) + ((nbits % 8) > 0);
24 //convert hex digit to integer
25 uint8_t hex2int(char hexchar) {
26 switch (hexchar) {
27 case '0':
28 return 0;
29 break;
30 case '1':
31 return 1;
32 break;
33 case '2':
34 return 2;
35 break;
36 case '3':
37 return 3;
38 break;
39 case '4':
40 return 4;
41 break;
42 case '5':
43 return 5;
44 break;
45 case '6':
46 return 6;
47 break;
48 case '7':
49 return 7;
50 break;
51 case '8':
52 return 8;
53 break;
54 case '9':
55 return 9;
56 break;
57 case 'a':
58 case 'A':
59 return 10;
60 break;
61 case 'b':
62 case 'B':
63 return 11;
64 break;
65 case 'c':
66 case 'C':
67 return 12;
68 break;
69 case 'd':
70 case 'D':
71 return 13;
72 break;
73 case 'e':
74 case 'E':
75 return 14;
76 break;
77 case 'f':
78 case 'F':
79 return 15;
80 break;
81 default:
82 return 0;
86 void LEDsoff(void) {
87 LED_A_OFF();
88 LED_B_OFF();
89 LED_C_OFF();
90 LED_D_OFF();
93 //ICEMAN: LED went from 1,2,3,4 -> 1,2,4,8
94 void LED(int led, int ms) {
95 if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
96 LED_A_ON();
97 if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
98 LED_B_ON();
99 if (led & LED_C) // Proxmark3 historical mapping: LED_RED
100 LED_C_ON();
101 if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
102 LED_D_ON();
104 if (!ms)
105 return;
107 SpinDelay(ms);
109 if (led & LED_A)
110 LED_A_OFF();
111 if (led & LED_B)
112 LED_B_OFF();
113 if (led & LED_C)
114 LED_C_OFF();
115 if (led & LED_D)
116 LED_D_OFF();
119 void SpinOff(uint32_t pause) {
120 LED_A_OFF();
121 LED_B_OFF();
122 LED_C_OFF();
123 LED_D_OFF();
124 SpinDelay(pause);
127 // Blinks..
128 // A = 1, B = 2, C = 4, D = 8
129 void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
130 SpinOff(speed);
131 NTIME(times) {
133 if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
134 LED_A_INV();
135 if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
136 LED_B_INV();
137 if (led & LED_C) // Proxmark3 historical mapping: LED_RED
138 LED_C_INV();
139 if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
140 LED_D_INV();
142 SpinDelay(speed);
144 LED_A_OFF();
145 LED_B_OFF();
146 LED_C_OFF();
147 LED_D_OFF();
150 void SpinDown(uint32_t speed) {
151 SpinOff(speed);
152 LED_D_ON();
153 SpinDelay(speed);
154 LED_D_OFF();
155 LED_C_ON();
156 SpinDelay(speed);
157 LED_C_OFF();
158 LED_B_ON();
159 SpinDelay(speed);
160 LED_B_OFF();
161 LED_A_ON();
162 SpinDelay(speed);
163 LED_A_OFF();
166 void SpinUp(uint32_t speed) {
167 SpinOff(speed);
168 LED_A_ON();
169 SpinDelay(speed);
170 LED_A_OFF();
171 LED_B_ON();
172 SpinDelay(speed);
173 LED_B_OFF();
174 LED_C_ON();
175 SpinDelay(speed);
176 LED_C_OFF();
177 LED_D_ON();
178 SpinDelay(speed);
179 LED_D_OFF();
183 // Determine if a button is double clicked, single clicked,
184 // not clicked, or held down (for ms || 1sec)
185 // In general, don't use this function unless you expect a
186 // double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
187 int BUTTON_CLICKED(int ms) {
188 // Up to 500ms in between clicks to mean a double click
189 // timer counts in 21.3us increments (1024/48MHz)
190 // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
191 if (ms > 1390) {
192 if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_CLICKED called with %i > 1390"), ms);
193 ms = 1390;
195 int ticks = ((MCK / 1000) * (ms ? ms : 1000)) >> 10;
197 // If we're not even pressed, forget about it!
198 if (!BUTTON_PRESS())
199 return BUTTON_NO_CLICK;
201 // Borrow a PWM unit for my real-time clock
202 AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
203 // 48 MHz / 1024 gives 46.875 kHz
204 AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
205 AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
206 AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
208 uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
210 int letoff = 0;
211 for (;;) {
212 uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
214 // We haven't let off the button yet
215 if (!letoff) {
216 // We just let it off!
217 if (!BUTTON_PRESS()) {
218 letoff = 1;
220 // reset our timer for 500ms
221 start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
222 ticks = ((MCK / 1000) * (500)) >> 10;
225 // Still haven't let it off
226 else
227 // Have we held down a full second?
228 if (now == (uint16_t)(start + ticks))
229 return BUTTON_HOLD;
232 // We already let off, did we click again?
233 else
234 // Sweet, double click!
235 if (BUTTON_PRESS())
236 return BUTTON_DOUBLE_CLICK;
238 // Have we ran out of time to double click?
239 else if (now == (uint16_t)(start + ticks))
240 // At least we did a single click
241 return BUTTON_SINGLE_CLICK;
243 WDT_HIT();
246 // We should never get here
247 return BUTTON_ERROR;
250 // Determine if a button is held down
251 int BUTTON_HELD(int ms) {
252 // timer counts in 21.3us increments (1024/48MHz)
253 // WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
254 if (ms > 1390) {
255 if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_HELD called with %i > 1390"), ms);
256 ms = 1390;
258 // If button is held for one second
259 int ticks = (48000 * (ms ? ms : 1000)) >> 10;
261 // If we're not even pressed, forget about it!
262 if (!BUTTON_PRESS())
263 return BUTTON_NO_CLICK;
265 // Borrow a PWM unit for my real-time clock
266 AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
267 // 48 MHz / 1024 gives 46.875 kHz
268 AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
269 AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
270 AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
272 uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
274 for (;;) {
275 uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
277 // As soon as our button let go, we didn't hold long enough
278 if (!BUTTON_PRESS())
279 return BUTTON_SINGLE_CLICK;
281 // Have we waited the full second?
282 else if (now == (uint16_t)(start + ticks))
283 return BUTTON_HOLD;
285 WDT_HIT();
288 // We should never get here
289 return BUTTON_ERROR;
292 bool data_available(void) {
293 #ifdef WITH_FPC_USART_HOST
294 return usb_poll_validate_length() || (usart_rxdata_available() > 0);
295 #else
296 return usb_poll_validate_length();
297 #endif