mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
Added stand-alone mode (no PC) with HID reading and cloning, moved helper functions to util.c
This commit is contained in:
parent
a52a7d191b
commit
955fc5e2f8
3 changed files with 345 additions and 57 deletions
198
armsrc/appmain.c
198
armsrc/appmain.c
|
@ -17,6 +17,7 @@
|
||||||
// The large multi-purpose buffer, typically used to hold A/D samples,
|
// The large multi-purpose buffer, typically used to hold A/D samples,
|
||||||
// maybe pre-processed in some way.
|
// maybe pre-processed in some way.
|
||||||
DWORD BigBuf[16000];
|
DWORD BigBuf[16000];
|
||||||
|
int usbattached = 0;
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// A buffer where we can queue things up to be sent through the FPGA, for
|
// A buffer where we can queue things up to be sent through the FPGA, for
|
||||||
|
@ -67,6 +68,10 @@ void ToSendStuffBit(int b)
|
||||||
|
|
||||||
void DbpString(char *str)
|
void DbpString(char *str)
|
||||||
{
|
{
|
||||||
|
/* this holds up stuff unless we're connected to usb */
|
||||||
|
if (!usbattached)
|
||||||
|
return;
|
||||||
|
|
||||||
UsbCommand c;
|
UsbCommand c;
|
||||||
c.cmd = CMD_DEBUG_PRINT_STRING;
|
c.cmd = CMD_DEBUG_PRINT_STRING;
|
||||||
c.ext1 = strlen(str);
|
c.ext1 = strlen(str);
|
||||||
|
@ -79,6 +84,10 @@ void DbpString(char *str)
|
||||||
|
|
||||||
void DbpIntegers(int x1, int x2, int x3)
|
void DbpIntegers(int x1, int x2, int x3)
|
||||||
{
|
{
|
||||||
|
/* this holds up stuff unless we're connected to usb */
|
||||||
|
if (!usbattached)
|
||||||
|
return;
|
||||||
|
|
||||||
UsbCommand c;
|
UsbCommand c;
|
||||||
c.cmd = CMD_DEBUG_PRINT_INTEGERS;
|
c.cmd = CMD_DEBUG_PRINT_INTEGERS;
|
||||||
c.ext1 = x1;
|
c.ext1 = x1;
|
||||||
|
@ -320,7 +329,7 @@ void MeasureAntennaTuning(void)
|
||||||
UsbSendPacket((BYTE *)&c, sizeof(c));
|
UsbSendPacket((BYTE *)&c, sizeof(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimulateTagLowFrequency(int period)
|
void SimulateTagLowFrequency(int period, int ledcontrol)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
BYTE *tab = (BYTE *)BigBuf;
|
BYTE *tab = (BYTE *)BigBuf;
|
||||||
|
@ -345,13 +354,16 @@ void SimulateTagLowFrequency(int period)
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
LED_D_ON();
|
if (ledcontrol)
|
||||||
if(tab[i]) {
|
LED_D_ON();
|
||||||
|
|
||||||
|
if(tab[i])
|
||||||
OPEN_COIL();
|
OPEN_COIL();
|
||||||
} else {
|
else
|
||||||
SHORT_COIL();
|
SHORT_COIL();
|
||||||
}
|
|
||||||
LED_D_OFF();
|
if (ledcontrol)
|
||||||
|
LED_D_OFF();
|
||||||
|
|
||||||
while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {
|
while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {
|
||||||
if(BUTTON_PRESS()) {
|
if(BUTTON_PRESS()) {
|
||||||
|
@ -415,7 +427,7 @@ static void fc(int c, int *n) {
|
||||||
|
|
||||||
// prepare a waveform pattern in the buffer based on the ID given then
|
// prepare a waveform pattern in the buffer based on the ID given then
|
||||||
// simulate a HID tag until the button is pressed
|
// simulate a HID tag until the button is pressed
|
||||||
static void CmdHIDsimTAG(int hi, int lo)
|
static void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
|
||||||
{
|
{
|
||||||
int n=0, i=0;
|
int n=0, i=0;
|
||||||
/*
|
/*
|
||||||
|
@ -461,13 +473,16 @@ static void CmdHIDsimTAG(int hi, int lo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LED_A_ON();
|
if (ledcontrol)
|
||||||
SimulateTagLowFrequency(n);
|
LED_A_ON();
|
||||||
LED_A_OFF();
|
SimulateTagLowFrequency(n, ledcontrol);
|
||||||
|
|
||||||
|
if (ledcontrol)
|
||||||
|
LED_A_OFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop to capture raw HID waveform then FSK demodulate the TAG ID from it
|
// loop to capture raw HID waveform then FSK demodulate the TAG ID from it
|
||||||
static void CmdHIDdemodFSK(void)
|
static void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||||
{
|
{
|
||||||
BYTE *dest = (BYTE *)BigBuf;
|
BYTE *dest = (BYTE *)BigBuf;
|
||||||
int m=0, n=0, i=0, idx=0, found=0, lastval=0;
|
int m=0, n=0, i=0, idx=0, found=0, lastval=0;
|
||||||
|
@ -487,10 +502,12 @@ static void CmdHIDdemodFSK(void)
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
LED_A_ON();
|
if (ledcontrol)
|
||||||
|
LED_A_ON();
|
||||||
if(BUTTON_PRESS()) {
|
if(BUTTON_PRESS()) {
|
||||||
DbpString("Stopped");
|
DbpString("Stopped");
|
||||||
LED_A_OFF();
|
if (ledcontrol)
|
||||||
|
LED_A_OFF();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +517,8 @@ static void CmdHIDdemodFSK(void)
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||||
SSC_TRANSMIT_HOLDING = 0x43;
|
SSC_TRANSMIT_HOLDING = 0x43;
|
||||||
LED_D_ON();
|
if (ledcontrol)
|
||||||
|
LED_D_ON();
|
||||||
}
|
}
|
||||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||||
dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
|
dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
|
||||||
|
@ -508,7 +526,8 @@ static void CmdHIDdemodFSK(void)
|
||||||
// threshold essentially we capture zero crossings for later analysis
|
// threshold essentially we capture zero crossings for later analysis
|
||||||
if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
|
if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
|
||||||
i++;
|
i++;
|
||||||
LED_D_OFF();
|
if (ledcontrol)
|
||||||
|
LED_D_OFF();
|
||||||
if(i >= m) {
|
if(i >= m) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -607,6 +626,13 @@ static void CmdHIDdemodFSK(void)
|
||||||
if (found && (hi|lo)) {
|
if (found && (hi|lo)) {
|
||||||
DbpString("TAG ID");
|
DbpString("TAG ID");
|
||||||
DbpIntegers(hi, lo, (lo>>1)&0xffff);
|
DbpIntegers(hi, lo, (lo>>1)&0xffff);
|
||||||
|
/* if we're only looking for one tag */
|
||||||
|
if (findone)
|
||||||
|
{
|
||||||
|
*high = hi;
|
||||||
|
*low = lo;
|
||||||
|
return;
|
||||||
|
}
|
||||||
hi=0;
|
hi=0;
|
||||||
lo=0;
|
lo=0;
|
||||||
found=0;
|
found=0;
|
||||||
|
@ -633,6 +659,13 @@ static void CmdHIDdemodFSK(void)
|
||||||
if (found && (hi|lo)) {
|
if (found && (hi|lo)) {
|
||||||
DbpString("TAG ID");
|
DbpString("TAG ID");
|
||||||
DbpIntegers(hi, lo, (lo>>1)&0xffff);
|
DbpIntegers(hi, lo, (lo>>1)&0xffff);
|
||||||
|
/* if we're only looking for one tag */
|
||||||
|
if (findone)
|
||||||
|
{
|
||||||
|
*high = hi;
|
||||||
|
*low = lo;
|
||||||
|
return;
|
||||||
|
}
|
||||||
hi=0;
|
hi=0;
|
||||||
lo=0;
|
lo=0;
|
||||||
found=0;
|
found=0;
|
||||||
|
@ -759,11 +792,11 @@ void UsbPacketReceived(BYTE *packet, int len)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_HID_DEMOD_FSK:
|
case CMD_HID_DEMOD_FSK:
|
||||||
CmdHIDdemodFSK(); // Demodulate HID tag
|
CmdHIDdemodFSK(0, 0, 0, 1); // Demodulate HID tag
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_HID_SIM_TAG:
|
case CMD_HID_SIM_TAG:
|
||||||
CmdHIDsimTAG(c->ext1, c->ext2); // Simulate HID tag by ID
|
CmdHIDsimTAG(c->ext1, c->ext2, 1); // Simulate HID tag by ID
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
|
case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
|
||||||
|
@ -792,7 +825,7 @@ void UsbPacketReceived(BYTE *packet, int len)
|
||||||
}
|
}
|
||||||
case CMD_SIMULATE_TAG_125K:
|
case CMD_SIMULATE_TAG_125K:
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
SimulateTagLowFrequency(c->ext1);
|
SimulateTagLowFrequency(c->ext1, 1);
|
||||||
LED_A_OFF();
|
LED_A_OFF();
|
||||||
break;
|
break;
|
||||||
#ifdef WITH_LCD
|
#ifdef WITH_LCD
|
||||||
|
@ -887,54 +920,109 @@ void AppMain(void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
UsbPoll(FALSE);
|
usbattached = UsbPoll(FALSE);
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
if (BUTTON_HELD(1000) > 0)
|
||||||
|
SamyRun();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpinDelayUs(int us)
|
|
||||||
|
// samy's sniff and repeat routine
|
||||||
|
void SamyRun()
|
||||||
{
|
{
|
||||||
int ticks = (48*us) >> 10;
|
DbpString("Stand-alone mode! No PC necessary.");
|
||||||
|
|
||||||
// Borrow a PWM unit for my real-time clock
|
// 3 possible options? no just 2 for now
|
||||||
PWM_ENABLE = PWM_CHANNEL(0);
|
#define OPTS 2
|
||||||
// 48 MHz / 1024 gives 46.875 kHz
|
|
||||||
PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
|
|
||||||
PWM_CH_DUTY_CYCLE(0) = 0;
|
|
||||||
PWM_CH_PERIOD(0) = 0xffff;
|
|
||||||
|
|
||||||
WORD start = (WORD)PWM_CH_COUNTER(0);
|
int high[OPTS], low[OPTS];
|
||||||
|
|
||||||
for(;;) {
|
// Oooh pretty -- notify user we're in elite samy mode now
|
||||||
WORD now = (WORD)PWM_CH_COUNTER(0);
|
LED(LED_RED, 200);
|
||||||
if(now == (WORD)(start + ticks)) {
|
LED(LED_ORANGE, 200);
|
||||||
return;
|
LED(LED_GREEN, 200);
|
||||||
}
|
LED(LED_ORANGE, 200);
|
||||||
|
LED(LED_RED, 200);
|
||||||
|
LED(LED_ORANGE, 200);
|
||||||
|
LED(LED_GREEN, 200);
|
||||||
|
LED(LED_ORANGE, 200);
|
||||||
|
LED(LED_RED, 200);
|
||||||
|
|
||||||
|
int selected = 0;
|
||||||
|
int playing = 0;
|
||||||
|
|
||||||
|
// Turn on selected LED
|
||||||
|
LED(selected + 1, 0);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
usbattached = UsbPoll(FALSE);
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
// Was our button held down or pressed?
|
||||||
|
int button_pressed = BUTTON_HELD(1000);
|
||||||
|
SpinDelay(300);
|
||||||
|
|
||||||
|
// Button was held for a second, begin recording
|
||||||
|
if (button_pressed > 0)
|
||||||
|
{
|
||||||
|
LEDsoff();
|
||||||
|
LED(selected + 1, 0);
|
||||||
|
LED(LED_RED2, 0);
|
||||||
|
|
||||||
|
// record
|
||||||
|
DbpString("Starting recording");
|
||||||
|
|
||||||
|
/* need this delay to prevent catching some weird data */
|
||||||
|
SpinDelay(500);
|
||||||
|
CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
|
||||||
|
DbpString("Recorded");
|
||||||
|
DbpIntegers(selected, high[selected], low[selected]);
|
||||||
|
|
||||||
|
LEDsoff();
|
||||||
|
LED(selected + 1, 0);
|
||||||
|
// Finished recording
|
||||||
|
|
||||||
|
// If we were previously playing, set playing off
|
||||||
|
// so next button push begins playing what we recorded
|
||||||
|
playing = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change where to record (or begin playing)
|
||||||
|
else if (button_pressed)
|
||||||
|
{
|
||||||
|
// Next option if we were previously playing
|
||||||
|
if (playing)
|
||||||
|
selected = (selected + 1) % OPTS;
|
||||||
|
playing = !playing;
|
||||||
|
|
||||||
|
LEDsoff();
|
||||||
|
LED(selected + 1, 0);
|
||||||
|
|
||||||
|
// Begin transmitting
|
||||||
|
if (playing)
|
||||||
|
{
|
||||||
|
LED(LED_GREEN, 0);
|
||||||
|
DbpString("Playing");
|
||||||
|
DbpIntegers(selected, high[selected], low[selected]);
|
||||||
|
CmdHIDsimTAG(high[selected], low[selected], 0);
|
||||||
|
DbpString("Done playing");
|
||||||
|
|
||||||
|
/* We pressed a button so ignore it here with a delay */
|
||||||
|
SpinDelay(300);
|
||||||
|
|
||||||
|
// when done, we're done playing, move to next option
|
||||||
|
selected = (selected + 1) % OPTS;
|
||||||
|
playing = !playing;
|
||||||
|
LEDsoff();
|
||||||
|
LED(selected + 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpinDelay(int ms)
|
|
||||||
{
|
|
||||||
int ticks = (48000*ms) >> 10;
|
|
||||||
|
|
||||||
// Borrow a PWM unit for my real-time clock
|
|
||||||
PWM_ENABLE = PWM_CHANNEL(0);
|
|
||||||
// 48 MHz / 1024 gives 46.875 kHz
|
|
||||||
PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
|
|
||||||
PWM_CH_DUTY_CYCLE(0) = 0;
|
|
||||||
PWM_CH_PERIOD(0) = 0xffff;
|
|
||||||
|
|
||||||
WORD start = (WORD)PWM_CH_COUNTER(0);
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
WORD now = (WORD)PWM_CH_COUNTER(0);
|
|
||||||
if(now == (WORD)(start + ticks)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
WDT_HIT();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// listen for external reader
|
// listen for external reader
|
||||||
void ListenReaderField(int limit)
|
void ListenReaderField(int limit)
|
||||||
|
|
|
@ -9,10 +9,9 @@
|
||||||
|
|
||||||
/// appmain.c
|
/// appmain.c
|
||||||
void AppMain(void);
|
void AppMain(void);
|
||||||
|
void SamyRun(void);
|
||||||
void DbpIntegers(int a, int b, int c);
|
void DbpIntegers(int a, int b, int c);
|
||||||
void DbpString(char *str);
|
void DbpString(char *str);
|
||||||
void SpinDelay(int ms);
|
|
||||||
void SpinDelayUs(int us);
|
|
||||||
void ToSendStuffBit(int b);
|
void ToSendStuffBit(int b);
|
||||||
void ToSendReset(void);
|
void ToSendReset(void);
|
||||||
void ListenReaderField(int limit);
|
void ListenReaderField(int limit);
|
||||||
|
@ -78,9 +77,24 @@ void ReaderIso15693(DWORD parameter); // Simulate an ISO15693 reader - greg
|
||||||
void SimTagIso15693(DWORD parameter); // simulate an ISO15693 tag - greg
|
void SimTagIso15693(DWORD parameter); // simulate an ISO15693 tag - greg
|
||||||
|
|
||||||
/// util.h
|
/// util.h
|
||||||
|
#define LED_RED 1
|
||||||
|
#define LED_ORANGE 2
|
||||||
|
#define LED_GREEN 4
|
||||||
|
#define LED_RED2 8
|
||||||
|
#define BUTTON_HOLD 1
|
||||||
|
#define BUTTON_NO_CLICK 0
|
||||||
|
#define BUTTON_SINGLE_CLICK -1
|
||||||
|
#define BUTTON_DOUBLE_CLICK -2
|
||||||
|
#define BUTTON_ERROR -99
|
||||||
int strlen(char *str);
|
int strlen(char *str);
|
||||||
void *memcpy(void *dest, const void *src, int len);
|
void *memcpy(void *dest, const void *src, int len);
|
||||||
void *memset(void *dest, int c, int len);
|
void *memset(void *dest, int c, int len);
|
||||||
int memcmp(const void *av, const void *bv, int len);
|
int memcmp(const void *av, const void *bv, int len);
|
||||||
|
void SpinDelay(int ms);
|
||||||
|
void SpinDelayUs(int us);
|
||||||
|
void LED(int led, int ms);
|
||||||
|
void LEDsoff();
|
||||||
|
int BUTTON_CLICKED(int ms);
|
||||||
|
int BUTTON_HELD(int ms);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
186
armsrc/util.c
186
armsrc/util.c
|
@ -51,3 +51,189 @@ int strlen(char *str)
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LEDsoff()
|
||||||
|
{
|
||||||
|
LED_A_OFF();
|
||||||
|
LED_B_OFF();
|
||||||
|
LED_C_OFF();
|
||||||
|
LED_D_OFF();
|
||||||
|
}
|
||||||
|
|
||||||
|
// LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8]
|
||||||
|
void LED(int led, int ms)
|
||||||
|
{
|
||||||
|
if (led & LED_RED)
|
||||||
|
LED_C_ON();
|
||||||
|
if (led & LED_ORANGE)
|
||||||
|
LED_A_ON();
|
||||||
|
if (led & LED_GREEN)
|
||||||
|
LED_B_ON();
|
||||||
|
if (led & LED_RED2)
|
||||||
|
LED_D_ON();
|
||||||
|
|
||||||
|
if (!ms)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SpinDelay(ms);
|
||||||
|
|
||||||
|
if (led & LED_RED)
|
||||||
|
LED_C_OFF();
|
||||||
|
if (led & LED_ORANGE)
|
||||||
|
LED_A_OFF();
|
||||||
|
if (led & LED_GREEN)
|
||||||
|
LED_B_OFF();
|
||||||
|
if (led & LED_RED2)
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// Up to 500ms in between clicks to mean a double click
|
||||||
|
int ticks = (48000 * (ms ? ms : 1000)) >> 10;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
PWM_ENABLE = PWM_CHANNEL(0);
|
||||||
|
// 48 MHz / 1024 gives 46.875 kHz
|
||||||
|
PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
|
||||||
|
PWM_CH_DUTY_CYCLE(0) = 0;
|
||||||
|
PWM_CH_PERIOD(0) = 0xffff;
|
||||||
|
|
||||||
|
WORD start = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
|
||||||
|
int letoff = 0;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
WORD now = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
|
||||||
|
// We haven't let off the button yet
|
||||||
|
if (!letoff)
|
||||||
|
{
|
||||||
|
// We just let it off!
|
||||||
|
if (!BUTTON_PRESS())
|
||||||
|
{
|
||||||
|
letoff = 1;
|
||||||
|
|
||||||
|
// reset our timer for 500ms
|
||||||
|
start = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
ticks = (48000 * (500)) >> 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Still haven't let it off
|
||||||
|
else
|
||||||
|
// Have we held down a full second?
|
||||||
|
if (now == (WORD)(start + ticks))
|
||||||
|
return BUTTON_HOLD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We already let off, did we click again?
|
||||||
|
else
|
||||||
|
// Sweet, double click!
|
||||||
|
if (BUTTON_PRESS())
|
||||||
|
return BUTTON_DOUBLE_CLICK;
|
||||||
|
|
||||||
|
// Have we ran out of time to double click?
|
||||||
|
else
|
||||||
|
if (now == (WORD)(start + ticks))
|
||||||
|
// At least we did a single click
|
||||||
|
return BUTTON_SINGLE_CLICK;
|
||||||
|
|
||||||
|
WDT_HIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should never get here
|
||||||
|
return BUTTON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if a button is held down
|
||||||
|
int BUTTON_HELD(int ms)
|
||||||
|
{
|
||||||
|
// If button is held for one second
|
||||||
|
int ticks = (48000 * (ms ? ms : 1000)) >> 10;
|
||||||
|
|
||||||
|
// 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
|
||||||
|
PWM_ENABLE = PWM_CHANNEL(0);
|
||||||
|
// 48 MHz / 1024 gives 46.875 kHz
|
||||||
|
PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
|
||||||
|
PWM_CH_DUTY_CYCLE(0) = 0;
|
||||||
|
PWM_CH_PERIOD(0) = 0xffff;
|
||||||
|
|
||||||
|
WORD start = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
WORD now = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
|
||||||
|
// As soon as our button let go, we didn't hold long enough
|
||||||
|
if (!BUTTON_PRESS())
|
||||||
|
return BUTTON_SINGLE_CLICK;
|
||||||
|
|
||||||
|
// Have we waited the full second?
|
||||||
|
else
|
||||||
|
if (now == (WORD)(start + ticks))
|
||||||
|
return BUTTON_HOLD;
|
||||||
|
|
||||||
|
WDT_HIT();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should never get here
|
||||||
|
return BUTTON_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpinDelayUs(int us)
|
||||||
|
{
|
||||||
|
int ticks = (48*us) >> 10;
|
||||||
|
|
||||||
|
// Borrow a PWM unit for my real-time clock
|
||||||
|
PWM_ENABLE = PWM_CHANNEL(0);
|
||||||
|
// 48 MHz / 1024 gives 46.875 kHz
|
||||||
|
PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
|
||||||
|
PWM_CH_DUTY_CYCLE(0) = 0;
|
||||||
|
PWM_CH_PERIOD(0) = 0xffff;
|
||||||
|
|
||||||
|
WORD start = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
WORD now = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
if(now == (WORD)(start + ticks)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WDT_HIT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpinDelay(int ms)
|
||||||
|
{
|
||||||
|
int ticks = (48000*ms) >> 10;
|
||||||
|
|
||||||
|
// Borrow a PWM unit for my real-time clock
|
||||||
|
PWM_ENABLE = PWM_CHANNEL(0);
|
||||||
|
// 48 MHz / 1024 gives 46.875 kHz
|
||||||
|
PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
|
||||||
|
PWM_CH_DUTY_CYCLE(0) = 0;
|
||||||
|
PWM_CH_PERIOD(0) = 0xffff;
|
||||||
|
|
||||||
|
WORD start = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
WORD now = (WORD)PWM_CH_COUNTER(0);
|
||||||
|
if (now == (WORD)(start + ticks))
|
||||||
|
return;
|
||||||
|
|
||||||
|
WDT_HIT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue