svn commit: r244898 - user/adrian/ath_radar_stuff/lib/libradarpkt
Adrian Chadd
adrian at FreeBSD.org
Mon Dec 31 07:50:03 UTC 2012
Author: adrian
Date: Mon Dec 31 07:50:02 2012
New Revision: 244898
URL: http://svnweb.freebsd.org/changeset/base/244898
Log:
Begin fleshing out support to parse HT20 spectral scan samples.
These haven't yet even remotely been verified as correct; please don't
try to use it.
The frequency is hard-coded; I need to decode ic_freq.
Also, it's assuming HT20 format; I need to decode the MCS channel flags
from the radiotap header to determine whether it's a HT20 or HT40 channel
(and subsequent channel configuration for pri/ext frequencies.)
Modified:
user/adrian/ath_radar_stuff/lib/libradarpkt/ar9280_radar.c
user/adrian/ath_radar_stuff/lib/libradarpkt/pkt.h
Modified: user/adrian/ath_radar_stuff/lib/libradarpkt/ar9280_radar.c
==============================================================================
--- user/adrian/ath_radar_stuff/lib/libradarpkt/ar9280_radar.c Mon Dec 31 07:30:07 2012 (r244897)
+++ user/adrian/ath_radar_stuff/lib/libradarpkt/ar9280_radar.c Mon Dec 31 07:50:02 2012 (r244898)
@@ -45,11 +45,164 @@
#include "pkt.h"
#include "ar9280_radar.h"
+/* Relevant on Merlin and later */
+#define CH_SPECTRAL_EVENT 0x10
/* Relevant for Sowl and later */
#define EXT_CH_RADAR_EARLY_FOUND 0x04
#define EXT_CH_RADAR_FOUND 0x02
#define PRI_CH_RADAR_FOUND 0x01
+#define AR9280_SPECTRAL_SAMPLE_SIZE_HT20 60
+#define AR9280_SPECTRAL_SAMPLE_SIZE_HT40 135
+
+/*
+ * GPLed snippet from Zefir on the linux-wireless list; rewrite this
+ * soon!
+ */
+#if 0
+/*
+ * In my system the post-processed FFT raw data is transferred via a netlink
+ * interface to a spectral_proxy, that forwards it to a connected host for real-time
+ * inspection and visualization.
+
+ * The interpretation of the data is as follows: the reported values are given as
+ * magnitudes, which need to be scaled and converted to absolute power values based
+ * on the packets noise floor and RSSI values as follows:
+ * bin_sum = 10*log(sum[i=1..56](b(i)^2)
+ * power(i) = noise_floor + RSSI + 10*log(b(i)^2) - bin_sum
+
+ * The code fragment to convert magnitude to absolute power values looks like this
+ * (assuming you transferred the FFT and magnitude data to user space):
+*/
+bool
+convert_data(struct spectral_ht20_msg *msg)
+{
+ uint8_t *bin_pwr = msg->bin;
+ uint8_t *dc_pwr = msg->bin + SPECTRAL_NUM_BINS / 2;
+ int pwr_count = SPECTRAL_NUM_BINS;
+ int8_t rssi = msg->rssi;
+ int8_t max_scale = 1 << msg->max_exp;
+ int16_t max_mag = msg->max_magnitude;
+ int i;
+ int nf0 = msg->noise_floor;
+
+ float bsum = 0.0;
+
+ // DC value is invalid -> interpolate
+ *dc_pwr = (dc_pwr[-1] + dc_pwr[1]) / 2;
+
+ for (i = 0; i < pwr_count; i++)
+ bsum += (bin_pwr[i] * max_scale) * (bin_pwr[i] * max_scale);
+ bsum = log10f(bsum) * 10;
+
+ for (i = 0; i < pwr_count; i++) {
+ float pwr_val;
+ int16_t val = bin_pwr[i];
+
+ if (val == 0)
+ val = 1;
+
+ pwr_val = 20 * log10f((float) val * max_scale);
+ pwr_val += nf0 + rssi - bsum;
+
+ val = pwr_val;
+ bin_pwr[i] = val;
+ }
+ return true;
+}
+#endif
+
+/* XXX why do we need this? */
+static int8_t
+fix_max_index(uint8_t max_index)
+{
+ int8_t maxindex = max_index;
+ if (max_index > 32)
+ maxindex |= 0xe0;
+ else
+ maxindex &= ~0xe0;
+ maxindex += 29;
+ return maxindex;
+}
+
+static int
+ar9280_radar_spectral_decode_ht20(struct ieee80211_radiotap_header *rh,
+ const unsigned char *pkt, int len, struct radar_entry *re,
+ int cur_sample)
+{
+ int i;
+ struct radar_fft_entry *fe;
+
+ if (len < AR9280_SPECTRAL_SAMPLE_SIZE_HT20) {
+ return (-1);
+ }
+
+ fe = &re->re_spectral_entries[cur_sample];
+
+ /* Decode the bitmap weight, magnitude, max index */
+
+ fe->pri.max_magnitude =
+ (pkt[57] << 2) |
+ ((pkt[56] & 0xc0) >> 6) |
+ ((pkt[58] & 0x03) << 10);
+ fe->pri.bitmap_weight = pkt[56] & 0x3f;
+ fe->pri.max_index = fix_max_index(pkt[58] & 0x3f);
+ fe->max_exp = pkt[59] & 0x0f;
+
+ /* Decode each bin - the dBm calculation will come later */
+ for (i = 0; i < 56; i++) {
+ fe->pri.bins[i].raw_mag = pkt[i];
+ fe->pri.bins[i].adj_mag = fe->pri.bins[i].raw_mag << fe->max_exp;
+ }
+
+ /* Return OK */
+ return (0);
+}
+
+/*
+ * Decode a spectral scan frame, complete with whatever
+ * hilarity / bugs ensue.
+ *
+ * The known quirks:
+ *
+ * + The MAC may corrupt a frame - inserting, deleting
+ * and/or realigning things.
+ * + The FFT data can terminate at any time; there's no
+ * guarantee that we'll get a complete frame.
+ *
+ * Let's not handle these for now; we'll just tinker with this
+ * in the future.
+ */
+static int
+ar9280_radar_spectral_decode(struct ieee80211_radiotap_header *rh,
+ const unsigned char *pkt, int len, struct radar_entry *re)
+{
+ int i;
+ const unsigned char *fr = pkt;
+ int fr_len = len;
+
+
+ for (i = 0; i < MAX_SPECTRAL_SCAN_SAMPLES_PER_PKT; i++) {
+ /* HT20 or HT40? */
+ /* XXX hard-code HT20 */
+ if (ar9280_radar_spectral_decode_ht20(rh, fr, fr_len, re, i) != 0) {
+ break;
+ }
+ fr_len -= AR9280_SPECTRAL_SAMPLE_SIZE_HT20;
+ fr += AR9280_SPECTRAL_SAMPLE_SIZE_HT20;
+ if (fr_len < 0)
+ break;
+ }
+
+// printf(" Spectral: %d samples\n", i);
+ re->re_num_spectral_entries = i;
+
+ return (0);
+}
+
+/*
+ * Decode a normal radar frame.
+ */
int
ar9280_radar_decode(struct ieee80211_radiotap_header *rh,
const unsigned char *pkt, int len, struct radar_entry *re)
@@ -93,10 +246,11 @@ ar9280_radar_decode(struct ieee80211_rad
printf(", pri/ext rssi: %d/%d", pri_rssi, ext_rssi);
printf(" pri: %u", pkt[len - 3] & 0xff);
printf(" ext: %u", pkt[len - 2] & 0xff);
- printf(" flags: %s %s %s\n",
+ printf(" flags: %s %s %s %s\n",
pkt[len - 1] & PRI_CH_RADAR_FOUND ? "pri" : "",
pkt[len - 1] & EXT_CH_RADAR_FOUND ? "ext" : "",
- pkt[len - 1] & EXT_CH_RADAR_EARLY_FOUND ? "extearly" : ""
+ pkt[len - 1] & EXT_CH_RADAR_EARLY_FOUND ? "extearly" : "",
+ pkt[len - 1] & CH_SPECTRAL_EVENT ? "spectral" : ""
);
#endif
@@ -124,8 +278,13 @@ ar9280_radar_decode(struct ieee80211_rad
re->re_timestamp = tsf;
re->re_rssi = pri_rssi; /* XXX extension rssi? */
re->re_dur = pkt[len - 3]; /* XXX extension duration? */
- re->re_freq = 0;
+ re->re_freq = 2412; /* XXX DO this! */
+ re->re_num_spectral_entries = 0;
/* XXX flags? */
+ if (pkt[len - 1] & CH_SPECTRAL_EVENT) {
+ (void) ar9280_radar_spectral_decode(rh, pkt, len - 3, re);
+ }
+
return(1);
}
Modified: user/adrian/ath_radar_stuff/lib/libradarpkt/pkt.h
==============================================================================
--- user/adrian/ath_radar_stuff/lib/libradarpkt/pkt.h Mon Dec 31 07:30:07 2012 (r244897)
+++ user/adrian/ath_radar_stuff/lib/libradarpkt/pkt.h Mon Dec 31 07:50:02 2012 (r244898)
@@ -35,6 +35,31 @@
extern "C" {
#endif
+#define PKT_NUM_BINS 64
+
+#define MAX_SPECTRAL_SCAN_SAMPLES_PER_PKT 64
+
+struct radar_fft_bin {
+ int32_t dBm;
+ int32_t adj_mag;
+ uint8_t raw_mag; /* original magnitude */
+ uint8_t bitmap; /* whether this is strong/weak */
+ uint8_t pad[2];
+};
+
+struct radar_fft_entry {
+ int is_ht40; /* 1=HT40, 0=HT20 */
+
+ struct {
+ struct radar_fft_bin bins[PKT_NUM_BINS];
+ uint8_t max_index;
+ uint8_t bitmap_weight;
+ uint16_t max_magnitude;
+ } pri, ext;
+
+ uint8_t max_exp;
+};
+
struct radar_entry {
uint64_t re_timestamp;
uint32_t re_freq;
@@ -45,6 +70,10 @@ struct radar_entry {
*/
int32_t re_rssi;
uint32_t re_dur;
+
+ /* XXX make these optional at some point */
+ int re_num_spectral_entries;
+ struct radar_fft_entry re_spectral_entries[MAX_SPECTRAL_SCAN_SAMPLES_PER_PKT];
};
#ifdef __cplusplus
More information about the svn-src-user
mailing list