hackrf.js
Version:
Control HackRF devices from Node.js
138 lines • 5.05 kB
JavaScript
;
/**
* Contains validation logic and other computations
*/
/** */
Object.defineProperty(exports, "__esModule", { value: true });
exports.calcSampleRate = exports.checkInLength = exports.checkIFreq = exports.checkFreq = exports.checkLoFreq = exports.checkBasebandFilterBw = exports.rangeChecker = exports.checkSpiflashAddress = exports.checkRffc5071Value = exports.checkRffc5071Reg = exports.checkSi5351cValue = exports.checkSi5351cReg = exports.checkMax2837Value = exports.checkMax2837Reg = exports.checkU16 = exports.checkU8 = exports.bitChecker = exports.checkU32 = exports.HackrfError = exports.computeBasebandFilterBw = exports.computeBasebandFilterBwRoundDownLt = exports.max2837_ft = void 0;
const constants_1 = require("./constants");
/** each entry is a uint32 (bandwidth in hz) */
exports.max2837_ft = [
1750000,
2500000,
3500000,
5000000,
5500000,
6000000,
7000000,
8000000,
9000000,
10000000,
12000000,
14000000,
15000000,
20000000,
24000000,
28000000,
];
/**
* Compute nearest freq for bw filter (manual filter)
*
* Return final bw round down and less than expected bw.
*/
function computeBasebandFilterBwRoundDownLt(bandwidthHz) {
checkU32(bandwidthHz);
let idx;
for (idx = 0; idx < exports.max2837_ft.length; idx++) {
if (exports.max2837_ft[idx] >= bandwidthHz)
break;
}
// Round down (if no equal to first entry)
idx = Math.max(idx - 1, 0);
return exports.max2837_ft[idx];
}
exports.computeBasebandFilterBwRoundDownLt = computeBasebandFilterBwRoundDownLt;
/**
* Compute best default value depending on sample rate (auto filter)
*
* Return final bw
*/
function computeBasebandFilterBw(bandwidthHz) {
checkU32(bandwidthHz);
let idx;
for (idx = 0; idx < exports.max2837_ft.length; idx++) {
if (exports.max2837_ft[idx] >= bandwidthHz)
break;
}
// Round down (if no equal to first entry) and if > bandwidthHz
if (exports.max2837_ft[idx] >= bandwidthHz)
idx = Math.max(idx - 1, 0);
return exports.max2837_ft[idx];
}
exports.computeBasebandFilterBw = computeBasebandFilterBw;
// VALIDATION
class HackrfError extends Error {
constructor(code) {
super(constants_1.ErrorCode[code]);
this.code = code;
this.name = 'HackrfError';
}
}
exports.HackrfError = HackrfError;
function checkU32(x) {
if ((x >>> 0) === x)
return x;
throw new HackrfError(constants_1.ErrorCode.INVALID_PARAM);
}
exports.checkU32 = checkU32;
// We do it with & because this also makes sure the passed
// number is a valid int32. bits must be <= 31
exports.bitChecker = (bits) => (x) => {
const mask = (1 << bits) - 1;
if ((x & mask) === x)
return x;
throw new HackrfError(constants_1.ErrorCode.INVALID_PARAM);
};
exports.checkU8 = exports.bitChecker(8);
exports.checkU16 = exports.bitChecker(16);
exports.checkMax2837Reg = exports.bitChecker(5);
exports.checkMax2837Value = exports.bitChecker(10);
exports.checkSi5351cReg = exports.bitChecker(8);
exports.checkSi5351cValue = exports.bitChecker(8);
function checkRffc5071Reg(x) {
if (checkU32(x) < 31)
return x;
throw new HackrfError(constants_1.ErrorCode.INVALID_PARAM);
}
exports.checkRffc5071Reg = checkRffc5071Reg;
exports.checkRffc5071Value = exports.bitChecker(16);
exports.checkSpiflashAddress = exports.bitChecker(20);
exports.rangeChecker = (min, max) => (x) => {
if (x >= min && x <= max)
return x;
throw new HackrfError(constants_1.ErrorCode.INVALID_PARAM);
};
exports.checkBasebandFilterBw = exports.rangeChecker(constants_1.BASEBAND_FILTER_BW_MIN, constants_1.BASEBAND_FILTER_BW_MAX);
exports.checkLoFreq = exports.rangeChecker(constants_1.LO_FREQ_HZ_MIN, constants_1.LO_FREQ_HZ_MAX);
exports.checkFreq = exports.rangeChecker(constants_1.FREQ_HZ_MIN, constants_1.FREQ_HZ_MAX);
exports.checkIFreq = exports.rangeChecker(constants_1.IF_HZ_MIN, constants_1.IF_HZ_MAX);
function checkInLength(buf, minLength) {
if (buf.length >= minLength)
return buf;
throw new HackrfError(constants_1.ErrorCode.LIBUSB);
}
exports.checkInLength = checkInLength;
// SAMPLE RATE CALCULATION
const f64toU = (x) => {
const f64a = Float64Array.of(x);
return new BigUint64Array(f64a.buffer, f64a.byteOffset)[0];
};
function chooseDivider(n) {
const n1 = BigInt(1), mask = (n1 << BigInt(52)) - n1;
const e = Number(f64toU(n) >> BigInt(52)) - 1023;
const fracN = 1 + n - Math.floor(n);
const frac = f64toU(fracN) & mask;
const round = (x) => (x + (n1 << BigInt(51))) & ~mask;
const roundError = (x) => Math.abs(Number(x - round(x)));
for (let divider = 1; divider <= 31; divider++) {
if (roundError(BigInt(divider) * frac) < 2 ** (e + 4))
return divider;
}
return 1;
}
function calcSampleRate(freqHz) {
const divider = chooseDivider(freqHz);
return [Math.round(freqHz * divider), divider];
}
exports.calcSampleRate = calcSampleRate;
//# sourceMappingURL=util.js.map