Research, development and trades concerning the powerful Proxmark3 device.
Remember; sharing is caring. Bring something back to the community.
"Learn the tools of the trade the hard way." +Fravia
You are not logged in.
Time changes and with it the technology
Proxmark3 @ discord
Users of this forum, please be aware that information stored on this site is not private.
Hello,
I submit this patch to improve the precision of LF and HF voltage measurements:
diff -ruN proxmark3.PREV/armsrc/appmain.c proxmark3/armsrc/appmain.c
--- proxmark3.PREV/armsrc/appmain.c 2020-05-21 01:05:55.164649483 +0300
+++ proxmark3/armsrc/appmain.c 2020-06-09 20:42:36.055373571 +0300
@@ -108,7 +108,7 @@
//-----------------------------------------------------------------------------
// Read an ADC channel and block till it completes, then return the result
-// in ADC units (0 to 1023). Also a routine to average 32 samples and
+// in ADC units (0 to 1023). Also a routine to sum up a number of samples and
// return that.
//-----------------------------------------------------------------------------
static uint16_t ReadAdc(int ch) {
@@ -137,13 +137,12 @@
}
// was static - merlok
-uint16_t AvgAdc(int ch) {
+uint16_t SumAdc(int ch, int NbSamples) {
uint16_t a = 0;
- for (uint8_t i = 0; i < 32; i++)
+ for (uint8_t i = 0; i < NbSamples; i++)
a += ReadAdc(ch);
- //division by 32
- return (a + 15) >> 5;
+ return (a + (NbSamples >> 1) - 1);
}
static void MeasureAntennaTuning(void) {
@@ -186,7 +185,7 @@
WDT_HIT();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
SpinDelay(20);
- uint32_t adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
+ uint32_t adcval = ((MAX_ADC_LF_VOLTAGE * (SumAdc(ADC_CHAN_LF, 32) >> 1)) >> 14);
if (i == LF_DIVISOR_125)
payload.v_lf125 = adcval; // voltage at 125kHz
@@ -212,9 +211,9 @@
SpinDelay(50);
#if defined RDV4
- payload.v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
+ payload.v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15;
#else
- payload.v_hf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+ payload.v_hf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
#endif
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@@ -226,16 +225,16 @@
static uint16_t MeasureAntennaTuningHfData(void) {
#if defined RDV4
- return (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
+ return (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15;
#else
- return (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+ return (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 64)) >> 16;
#endif
}
// Measure LF in milliVolt
static uint32_t MeasureAntennaTuningLfData(void) {
- return (MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10;
+ return (MAX_ADC_LF_VOLTAGE * (SumAdc(ADC_CHAN_LF, 32) >> 1)) >> 14;
}
void ReadMem(int addr) {
@@ -541,7 +540,7 @@
LEDsoff();
if (limit == LF_ONLY) {
- lf_av = lf_max = AvgAdc(ADC_CHAN_LF);
+ lf_av = lf_max = SumAdc(ADC_CHAN_LF, 32) >> 5;
Dbprintf("LF 125/134kHz Baseline: %dmV", (MAX_ADC_LF_VOLTAGE * lf_av) >> 10);
lf_baseline = lf_av;
}
@@ -550,9 +549,9 @@
#if defined RDV4
// iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader.
- hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40);
+ hf_av = hf_max = SumAdc(ADC_CHAN_HF_RDV40, 32) >> 5;
#else
- hf_av = hf_max = AvgAdc(ADC_CHAN_HF);
+ hf_av = hf_max = SumAdc(ADC_CHAN_HF, 32) >> 5;
#endif
Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10);
hf_baseline = hf_av;
@@ -586,7 +585,7 @@
LED_D_OFF();
}
- lf_av_new = AvgAdc(ADC_CHAN_LF);
+ lf_av_new = SumAdc(ADC_CHAN_LF, 32) >> 5;
// see if there's a significant change
if (ABS(lf_av - lf_av_new) > REPORT_CHANGE) {
Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
@@ -605,9 +604,9 @@
}
#if defined RDV4
- hf_av_new = AvgAdc(ADC_CHAN_HF_RDV40);
+ hf_av_new = SumAdc(ADC_CHAN_HF_RDV40, 32) >> 5;
#else
- hf_av_new = AvgAdc(ADC_CHAN_HF);
+ hf_av_new = SumAdc(ADC_CHAN_HF, 32) >> 5;
#endif
// see if there's a significant change
if (ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
diff -ruN proxmark3.PREV/armsrc/appmain.h proxmark3/armsrc/appmain.h
--- proxmark3.PREV/armsrc/appmain.h 2020-05-21 01:05:55.164649483 +0300
+++ proxmark3/armsrc/appmain.h 2020-06-09 20:06:04.861879237 +0300
@@ -30,7 +30,7 @@
void ReadMem(int addr);
void __attribute__((noreturn)) AppMain(void);
-uint16_t AvgAdc(int ch);
+uint16_t SumAdc(int ch, int NbSamples);
//void PrintToSendBuffer(void);
void ToSendStuffBit(int b);
diff -ruN proxmark3.PREV/armsrc/iso14443b.c proxmark3/armsrc/iso14443b.c
--- proxmark3.PREV/armsrc/iso14443b.c 2020-05-21 01:05:55.176648825 +0300
+++ proxmark3/armsrc/iso14443b.c 2020-06-09 20:08:06.407588973 +0300
@@ -641,9 +641,9 @@
if (cardSTATE == SIM_NOFIELD) {
#if defined RDV4
- vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
+ vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15;
#else
- vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+ vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
#endif
if (vHf > MF_MINFIELDV) {
cardSTATE = SIM_IDLE;
diff -ruN proxmark3.PREV/armsrc/lfops.c proxmark3/armsrc/lfops.c
--- proxmark3.PREV/armsrc/lfops.c 2020-05-21 01:05:55.180648606 +0300
+++ proxmark3/armsrc/lfops.c 2020-06-09 20:47:01.775509550 +0300
@@ -1571,7 +1571,7 @@
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD);
// measure antenna strength.
- //int adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
+ //int adcval = ((MAX_ADC_LF_VOLTAGE * (SumAdc(ADC_CHAN_LF, 32) >> 1)) >> 14);
WaitUS(delay);
}
static void TurnReadLF_off(uint32_t delay) {
diff -ruN proxmark3.PREV/armsrc/mifaresim.c proxmark3/armsrc/mifaresim.c
--- proxmark3.PREV/armsrc/mifaresim.c 2020-05-21 01:05:55.184648387 +0300
+++ proxmark3/armsrc/mifaresim.c 2020-06-09 20:46:36.730015514 +0300
@@ -539,9 +539,9 @@
if (cardSTATE == MFEMUL_NOFIELD) {
#if defined RDV4
- vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10;
+ vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * SumAdc(ADC_CHAN_HF_RDV40, 32)) >> 15;
#else
- vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+ vHf = (MAX_ADC_HF_VOLTAGE * SumAdc(ADC_CHAN_HF, 32)) >> 15;
#endif
if (vHf > MF_MINFIELDV) {
diff -ruN proxmark3.PREV/armsrc/thinfilm.c proxmark3/armsrc/thinfilm.c
--- proxmark3.PREV/armsrc/thinfilm.c 2020-05-21 01:05:55.188648168 +0300
+++ proxmark3/armsrc/thinfilm.c 2020-06-09 20:43:37.241866121 +0300
@@ -53,9 +53,9 @@
static uint16_t ReadReaderField(void) {
#if defined RDV4
- return AvgAdc(ADC_CHAN_HF_RDV40);
+ return SumAdc(ADC_CHAN_HF_RDV40, 32) >> 5;
#else
- return AvgAdc(ADC_CHAN_HF);
+ return SumAdc(ADC_CHAN_HF, 32) >> 5;
#endif
}
Basically, it replaces the AvgAdc() function which clobbers 5 least significant bits before the voltage multiplication in the calling functions by a summation function, and the final division is performed inside the calling function after the multiplication, in a way that preserves as much of the original value with the integer formats available, without overflowing, depending on whether it's HF or LF and the applicable maximum voltage.
I made this patch because I want to turn my Proxmark3 into a musical instrument: I want to use it as a theremin, that I can play with my NFC and RFID implants To do this, I use the "hf tune" or "lf tune" and generate a tone depending on the antenna's voltage, which changes when a transponder enters the field.
No problem with a credit-card-sized tag: it generates voltage swings in the order of 10V, so there are plenty of values between the minimum and maximum voltages to control the pitch precisely. However, with an implant, the voltage swing is 1V at best, and because of the lack of precision with the AvgAdc() function as it is currently implemented, there are only 4 or 5 values, or "notes" available. With my patch, the pitch control is much more precise.
To illustrate what I'm talking about, here's a video of my PM3 "theremin" without the patch, and here's another with the patch.
Of course, my purpose is rather silly, but better precision is always desirable, and possibly even beneficial for "serious" PM3 use in other functions.
(Incidentally, if you're interested in my little script to turn the PM3 into a theremin, you can find it on the DT forum here)
Last edited by Rosco (2020-06-10 10:28:09)
Offline
This must be the most intuitive way to use a Proxmark3 I have seen in a long long long time.
I'd hope you make a PR to the repo instead of the patch file here, anyway, I added your python script to the repo already.
Yes, we can use pyhton now as both embedded and external
Amazing bro!
Offline
Cool, thanks.
I'd hope you make a PR to the repo instead of the patch file here
Sorry, I've seen others post patches on the forum, I thought it was okay. I'll do it right next time.
Last edited by Rosco (2020-06-09 21:49:11)
Offline
No worries. I know you will.
Offline
Grait idea.
Save to midi will be ultimate fither.
But it not working to Windows, that's not good.
Offline
Save to midi will be ultimate fither.
An autotuner might be a better idea. It's not exactly easy to play.
But it not working to Windows, that's not good.
It's just a little something I coded for fun to kill time. I wasn't trying to make a portable audio app - nor was I expecting it to end up in the PM3 distro for that matter, since it's rather pointless Also I don't have Windows. Sorry... But I'm guessing it's trivial enough to be ported easily.
Last edited by Rosco (2020-06-10 03:26:40)
Offline
All merged
Offline
I saw that. Very groovy, thanks!
Offline
By the way, I saw this in your comment:
Reintroduce AvgAdv, avoid *64 as it could easily overflow
Damn, for some reason I was sure MAX_ADC_HF_VOLTAGE_RDV40 was the same value as MAX_ADC_HF_VOLTAGE, but I just rechecked and in fact it's 140800, like MAX_ADC_LF_VOLTAGE. Sorry about that, I didn't mean to introduce bugs. Good catch in any case!
Offline
well, your idea made the sensitivity for HF tune go from 137mV -> 4mV So your solution is better We had to adjust it a bit when we understood the idea behind it.
Offline