proxmark3/armsrc/util.c

299 lines
7.5 KiB
C
Raw Normal View History

//-----------------------------------------------------------------------------
// Jonathan Westhues, Sept 2005
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Utility functions used in many places, not specific to any piece of code.
//-----------------------------------------------------------------------------
#include "util.h"
#include "proxmark3_arm.h"
#include "ticks.h"
#include "commonutil.h"
#include "dbprint.h"
#include "string.h"
#include "usb_cdc.h"
#include "usart.h"
size_t nbytes(size_t nbits) {
2019-03-10 07:00:59 +08:00
return (nbits >> 3) + ((nbits % 8) > 0);
}
//convert hex digit to integer
uint8_t hex2int(char hexchar) {
2019-03-10 07:00:59 +08:00
switch (hexchar) {
case '0':
return 0;
break;
case '1':
return 1;
break;
case '2':
return 2;
break;
case '3':
return 3;
break;
case '4':
return 4;
break;
case '5':
return 5;
break;
case '6':
return 6;
break;
case '7':
return 7;
break;
case '8':
return 8;
break;
case '9':
return 9;
break;
case 'a':
2019-03-10 07:00:59 +08:00
case 'A':
return 10;
break;
case 'b':
2019-03-10 07:00:59 +08:00
case 'B':
return 11;
break;
case 'c':
2019-03-10 07:00:59 +08:00
case 'C':
return 12;
break;
case 'd':
2019-03-10 07:00:59 +08:00
case 'D':
return 13;
break;
case 'e':
2019-03-10 07:00:59 +08:00
case 'E':
return 14;
break;
case 'f':
2019-03-10 07:00:59 +08:00
case 'F':
return 15;
break;
default:
return 0;
}
}
2020-05-10 22:59:38 +08:00
void LEDsoff(void) {
2019-03-10 03:34:41 +08:00
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
}
2019-09-13 22:27:25 +08:00
//ICEMAN: LED went from 1,2,3,4 -> 1,2,4,8
void LED(int led, int ms) {
2019-06-02 17:47:10 +08:00
if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
2019-03-10 03:34:41 +08:00
LED_A_ON();
2019-06-02 17:47:10 +08:00
if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
2019-03-10 03:34:41 +08:00
LED_B_ON();
2019-06-02 17:47:10 +08:00
if (led & LED_C) // Proxmark3 historical mapping: LED_RED
LED_C_ON();
if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
2019-03-10 03:34:41 +08:00
LED_D_ON();
if (!ms)
return;
SpinDelay(ms);
2019-06-02 17:47:10 +08:00
if (led & LED_A)
2019-03-10 03:34:41 +08:00
LED_A_OFF();
2019-06-02 17:47:10 +08:00
if (led & LED_B)
2019-03-10 03:34:41 +08:00
LED_B_OFF();
2019-06-02 17:47:10 +08:00
if (led & LED_C)
LED_C_OFF();
if (led & LED_D)
2019-03-10 03:34:41 +08:00
LED_D_OFF();
}
void SpinOff(uint32_t pause) {
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
SpinDelay(pause);
}
// Blinks..
// A = 1, B = 2, C = 4, D = 8
void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
SpinOff(speed);
2019-03-10 07:00:59 +08:00
NTIME(times) {
if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
LED_A_INV();
if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
LED_B_INV();
if (led & LED_C) // Proxmark3 historical mapping: LED_RED
LED_C_INV();
if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
LED_D_INV();
SpinDelay(speed);
}
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
}
void SpinDown(uint32_t speed) {
SpinOff(speed);
LED_D_ON();
SpinDelay(speed);
LED_D_OFF();
LED_C_ON();
SpinDelay(speed);
LED_C_OFF();
LED_B_ON();
SpinDelay(speed);
LED_B_OFF();
LED_A_ON();
SpinDelay(speed);
LED_A_OFF();
}
void SpinUp(uint32_t speed) {
SpinOff(speed);
LED_A_ON();
SpinDelay(speed);
LED_A_OFF();
LED_B_ON();
SpinDelay(speed);
LED_B_OFF();
LED_C_ON();
SpinDelay(speed);
LED_C_OFF();
LED_D_ON();
SpinDelay(speed);
LED_D_OFF();
}
// Determine if a button is double clicked, single clicked,
// not clicked, or held down (for ms || 1sec)
// In general, don't use this function unless you expect a
// double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
int BUTTON_CLICKED(int ms) {
2019-03-10 03:34:41 +08:00
// Up to 500ms in between clicks to mean a double click
2019-08-06 19:51:10 +08:00
// timer counts in 21.3us increments (1024/48MHz)
// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
if (ms > 1390) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_CLICKED called with %i > 1390"), ms);
ms = 1390;
}
int ticks = ((MCK / 1000) * (ms ? ms : 1000)) >> 10;
2019-03-10 03:34:41 +08:00
// If we're not even pressed, forget about it!
if (!BUTTON_PRESS())
return BUTTON_NO_CLICK;
// Borrow a PWM unit for my real-time clock
AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
// 48 MHz / 1024 gives 46.875 kHz
AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
int letoff = 0;
2019-03-10 07:00:59 +08:00
for (;;) {
2019-03-10 03:34:41 +08:00
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// We haven't let off the button yet
2019-03-10 07:00:59 +08:00
if (!letoff) {
2019-03-10 03:34:41 +08:00
// We just let it off!
2019-03-10 07:00:59 +08:00
if (!BUTTON_PRESS()) {
2019-03-10 03:34:41 +08:00
letoff = 1;
// reset our timer for 500ms
start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
ticks = ((MCK / 1000) * (500)) >> 10;
2019-03-10 03:34:41 +08:00
}
// Still haven't let it off
else
// Have we held down a full second?
if (now == (uint16_t)(start + ticks))
2019-03-10 03:34:41 +08:00
return BUTTON_HOLD;
}
// We already let off, did we click again?
else
// Sweet, double click!
if (BUTTON_PRESS())
return BUTTON_DOUBLE_CLICK;
2019-03-10 07:00:59 +08:00
// Have we ran out of time to double click?
else if (now == (uint16_t)(start + ticks))
2019-03-10 07:00:59 +08:00
// At least we did a single click
return BUTTON_SINGLE_CLICK;
2019-03-10 03:34:41 +08:00
WDT_HIT();
}
// We should never get here
return BUTTON_ERROR;
}
// Determine if a button is held down
int BUTTON_HELD(int ms) {
2019-08-06 19:51:10 +08:00
// timer counts in 21.3us increments (1024/48MHz)
// WARNING: timer can't measure more than 1.39s (21.3us * 0xffff)
if (ms > 1390) {
if (DBGLEVEL >= DBG_ERROR) Dbprintf(_RED_("Error, BUTTON_HELD called with %i > 1390"), ms);
ms = 1390;
}
2019-03-10 03:34:41 +08:00
// If button is held for one second
int ticks = (48000 * (ms ? ms : 1000)) >> 10;
2019-03-10 03:34:41 +08:00
// If we're not even pressed, forget about it!
if (!BUTTON_PRESS())
return BUTTON_NO_CLICK;
2019-03-10 03:34:41 +08:00
// Borrow a PWM unit for my real-time clock
AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
// 48 MHz / 1024 gives 46.875 kHz
AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
2019-03-10 03:34:41 +08:00
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
2019-03-10 07:00:59 +08:00
for (;;) {
2019-03-10 03:34:41 +08:00
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
2019-03-10 03:34:41 +08:00
// As soon as our button let go, we didn't hold long enough
if (!BUTTON_PRESS())
return BUTTON_SINGLE_CLICK;
2019-03-10 03:34:41 +08:00
// Have we waited the full second?
else if (now == (uint16_t)(start + ticks))
2019-03-10 07:00:59 +08:00
return BUTTON_HOLD;
2019-03-10 03:34:41 +08:00
WDT_HIT();
}
2019-03-10 03:34:41 +08:00
// We should never get here
return BUTTON_ERROR;
}
bool data_available(void) {
#ifdef WITH_FPC_USART_HOST
return usb_poll_validate_length() || (usart_rxdata_available() > 0);
#else
return usb_poll_validate_length();
#endif
}