Proxmark3 community

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.

Announcement

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.

#1 2020-06-09 20:41:57

Rosco
Contributor
Registered: 2019-12-10
Posts: 43

[PATCH] Better precision for HF and LF voltage measurements

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 smile 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

#2 2020-06-09 21:21:09

iceman
Administrator
Registered: 2013-04-25
Posts: 9,538
Website

Re: [PATCH] Better precision for HF and LF voltage measurements

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 smile   

Amazing bro!

Offline

#3 2020-06-09 21:29:49

Rosco
Contributor
Registered: 2019-12-10
Posts: 43

Re: [PATCH] Better precision for HF and LF voltage measurements

Cool, thanks.

iceman wrote:

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

#4 2020-06-09 21:39:32

iceman
Administrator
Registered: 2013-04-25
Posts: 9,538
Website

Re: [PATCH] Better precision for HF and LF voltage measurements

No worries.  I know you will.

Offline

#5 2020-06-10 01:37:07

Winds
Member
Registered: 2020-01-28
Posts: 53

Re: [PATCH] Better precision for HF and LF voltage measurements

Grait idea.
Save to midi will be ultimate fither.

But it not working to Windows, that's not good.

Offline

#6 2020-06-10 03:25:57

Rosco
Contributor
Registered: 2019-12-10
Posts: 43

Re: [PATCH] Better precision for HF and LF voltage measurements

Winds wrote:

Save to midi will be ultimate fither.

An autotuner might be a better idea. It's not exactly easy to play.

Winds wrote:

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 smile 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

#7 2020-06-10 08:20:01

iceman
Administrator
Registered: 2013-04-25
Posts: 9,538
Website

Re: [PATCH] Better precision for HF and LF voltage measurements

All merged smile

Offline

#8 2020-06-10 10:13:39

Rosco
Contributor
Registered: 2019-12-10
Posts: 43

Re: [PATCH] Better precision for HF and LF voltage measurements

I saw that. Very groovy, thanks!

Offline

#9 2020-06-10 10:27:08

Rosco
Contributor
Registered: 2019-12-10
Posts: 43

Re: [PATCH] Better precision for HF and LF voltage measurements

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

#10 2020-06-10 12:51:02

iceman
Administrator
Registered: 2013-04-25
Posts: 9,538
Website

Re: [PATCH] Better precision for HF and LF voltage measurements

well,  your idea made the sensitivity for HF tune go from 137mV -> 4mV   So your solution is better smile  We had to adjust it a bit when we understood the idea behind it.

Offline

Board footer

Powered by FluxBB