diff --git a/CMakeLists.txt b/CMakeLists.txt index 503f161..baa8086 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ endif() OPTION(LINK_RTLTOOLS_AGAINST_STATIC_LIB "Link rtl-tools statically against librtlsdr" OFF) +OPTION(PROVIDE_UDP_SERVER "Provide UDP server for tests" OFF) # Set the version information here set(VERSION_INFO_MAJOR_VERSION 0) # increment major on api compatibility changes @@ -46,6 +47,10 @@ set(VERSION_INFO_MINOR_VERSION 7) # increment minor on feature-level changes set(VERSION_INFO_PATCH_VERSION git) # increment patch for bug fixes and docs include(Version) # setup version info +if(PROVIDE_UDP_SERVER AND WIN32) + add_definitions(-DWITH_UDP_SERVER) +endif() + ######################################################################## # Compiler specific setup ######################################################################## diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h index 98ea869..f08d2af 100755 --- a/include/tuner_r82xx.h +++ b/include/tuner_r82xx.h @@ -108,6 +108,8 @@ struct r82xx_priv { unsigned int haveR13H, valR13H; unsigned int haveR14L, valR14L; unsigned int haveR14H, valR14H; + unsigned int haveR30H, valR30H; + unsigned int haveR30L, valR30L; #endif }; @@ -133,8 +135,8 @@ int r82xx_init(struct r82xx_priv *priv); int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq); //int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain); int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain, int extended_mode, int lna_gain, int mixer_gain, int vga_gain); -int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsigned mask, unsigned data); -int r82xx_set_i2c_override(struct r82xx_priv *priv, unsigned i2c_register, unsigned mask, unsigned data); +int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsigned data, unsigned mask); +int r82xx_set_i2c_override(struct r82xx_priv *priv, unsigned i2c_register, unsigned data, unsigned mask); int r82xx_set_bandwidth(struct r82xx_priv *priv, int bandwidth, uint32_t rate, uint32_t * applied_bw, int apply); int r82xx_read_cache_reg(struct r82xx_priv *priv, int reg); diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 84d388d..ef9f52d 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -103,8 +103,8 @@ typedef struct rtlsdr_tuner_iface { int (*set_gain)(void *, int gain /* tenth dB */); int (*set_if_gain)(void *, int stage, int gain /* tenth dB */); int (*set_gain_mode)(void *, int manual); - int (*set_i2c_register)(void *, unsigned i2c_register, unsigned mask /* byte */, unsigned data /* byte */ ); - int (*set_i2c_override)(void *, unsigned i2c_register, unsigned mask /* byte */, unsigned data /* byte */ ); + int (*set_i2c_register)(void *, unsigned i2c_register, unsigned data /* byte */, unsigned mask /* byte */ ); + int (*set_i2c_override)(void *, unsigned i2c_register, unsigned data /* byte */, unsigned mask /* byte */ ); unsigned (*get_i2c_register)(void *, int i2c_register); } rtlsdr_tuner_iface_t; @@ -212,6 +212,7 @@ struct rtlsdr_dev { struct softagc_state softagc; /* UDP controller server */ +#ifdef WITH_UDP_SERVER #define UDP_TX_BUFLEN 128 unsigned udpPortNo; /* default: 32323 */ int override_if_freq; @@ -226,6 +227,7 @@ struct rtlsdr_dev { int recv_len; char buf[UDP_TX_BUFLEN]; WSADATA wsa; +#endif /* status */ int dev_lost; @@ -400,13 +402,13 @@ unsigned r820t_get_i2c_register(void *dev, int reg) { rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; return r82xx_read_cache_reg(&devt->r82xx_p,reg); } -int r820t_set_i2c_register(void *dev, unsigned i2c_register, unsigned mask, unsigned data ) { +int r820t_set_i2c_register(void *dev, unsigned i2c_register, unsigned data, unsigned mask ) { rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; - return r82xx_set_i2c_register(&devt->r82xx_p, i2c_register, mask, data); + return r82xx_set_i2c_register(&devt->r82xx_p, i2c_register, data, mask); } -int r820t_set_i2c_override(void *dev, unsigned i2c_register, unsigned mask, unsigned data ) { +int r820t_set_i2c_override(void *dev, unsigned i2c_register, unsigned data, unsigned mask ) { rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; - return r82xx_set_i2c_override(&devt->r82xx_p, i2c_register, mask, data); + return r82xx_set_i2c_override(&devt->r82xx_p, i2c_register, data, mask); } @@ -905,6 +907,7 @@ static int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq) if (rtlsdr_get_xtal_freq(dev, &rtl_xtal, NULL)) return -2; +#ifdef WITH_UDP_SERVER dev->last_if_freq = freq; if ( dev->override_if_flag ) { if ( dev->verbose ) @@ -914,6 +917,7 @@ static int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq) if ( dev->override_if_flag == 1 ) dev->override_if_flag = 0; } +#endif if_freq = ((freq * TWO_POW(22)) / rtl_xtal) * (-1); @@ -1165,7 +1169,7 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq) // restore filters if (dev->handled) { rtlsdr_set_i2c_repeater(dev, 1); - dev->tuner->set_i2c_register(dev, 27, 255, dev->saved_27); + dev->tuner->set_i2c_register(dev, 27, dev->saved_27, 255); rtlsdr_set_i2c_repeater(dev, 0); } @@ -1509,7 +1513,7 @@ int rtlsdr_set_tuner_i2c_register(rtlsdr_dev_t *dev, unsigned i2c_register, unsi if (dev->tuner->set_i2c_register) { rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->set_i2c_register((void *)dev, i2c_register, mask, data); + r = dev->tuner->set_i2c_register((void *)dev, i2c_register, data, mask); rtlsdr_set_i2c_repeater(dev, 0); } return r; @@ -1532,7 +1536,7 @@ int rtlsdr_set_tuner_i2c_override(rtlsdr_dev_t *dev, unsigned i2c_register, unsi if (dev->tuner->set_i2c_override) { rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->set_i2c_override((void *)dev, i2c_register, mask, data); + r = dev->tuner->set_i2c_override((void *)dev, i2c_register, data, mask); rtlsdr_set_i2c_repeater(dev, 0); } return r; @@ -2032,9 +2036,7 @@ int rtlsdr_get_index_by_serial(const char *serial) } /* UDP controller server */ -#if 0 -unsigned udpPortNo; /* default: 32323 */ -#endif +#ifdef WITH_UDP_SERVER static int parseNum(const char * pacNum) { int numBase = 10; /* assume decimal */ @@ -2230,16 +2232,6 @@ static int parse(char *message, rtlsdr_dev_t *dev) } } else if (comm == 64 +2 || comm == 64 +3 ) { dev->saved_27 = dev->tuner->get_i2c_register(dev,27); - if ( dev->tuner->set_i2c_register && dev->tuner->set_i2c_override ) { - rtlsdr_set_i2c_repeater(dev, 1); - if (comm == 64 +2) - val = dev->tuner->set_i2c_register(dev, reg, iVal, mask); - else - val = dev->tuner->set_i2c_override(dev, reg, iVal, mask); - rtlsdr_set_i2c_repeater(dev, 0); - } - sprintf(response,"! %d\n", (int)val); - // printf("%d %d %d\n", reg, val, mask); if ( dev->verbose ) { fprintf(stderr, "parsed 'set i2c register %s %d = x%02X value %d = %s = %s with mask %s = %s'\n" @@ -2249,6 +2241,20 @@ static int parse(char *message, rtlsdr_dev_t *dev) , formatInHex(hexBufB, (int)mask, 2), formatInBin(binBufB, (int)mask, 8) ); fprintf(stderr, "\tresponse: %s\n", response); } + if ( dev->tuner->set_i2c_register && dev->tuner->set_i2c_override ) { + rtlsdr_set_i2c_repeater(dev, 1); + if (comm == 64 +2) { + fprintf(stderr, "calling tuner->set_i2c_register( reg %d, value %02X, mask %02X)\n", reg, iVal, mask); + val = dev->tuner->set_i2c_register(dev, reg, iVal, mask); + } + else { + fprintf(stderr, "calling tuner->set_i2c_override( reg %d, value %02X, mask %02X)\n", reg, iVal, mask); + val = dev->tuner->set_i2c_override(dev, reg, iVal, mask); + } + rtlsdr_set_i2c_repeater(dev, 0); + } + sprintf(response,"! %d\n", (int)val); + // printf("%d %d %d\n", reg, val, mask); val = sendto(dev->udpS, response, strlen(response), 0, (struct sockaddr*) &dev->si_other, dev->slen); if ( val < 0 ) { // printf("error sending\n"); @@ -2334,6 +2340,8 @@ void * srv_server(void *vdev) return NULL; } +#endif + int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) { @@ -2376,11 +2384,13 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) dev->softagc.deadTimeSps = 0; dev->softagc.rpcNumGains = 0; dev->softagc.rpcGainValues = NULL; - + /* UDP controller server */ +#ifdef WITH_UDP_SERVER dev->udpPortNo = 0; /* default port 32323 .. but deactivated - by default */ dev->override_if_freq = 0; dev->override_if_flag = 0; +#endif dev->dev_num = index; dev->dev_lost = 1; @@ -3402,7 +3412,10 @@ const char * rtlsdr_get_opt_help(int longInfo) "\t[-O\tset RTL options string seperated with ':' ]\n" "\t\tf=:bw=:agc=:gain=\n" "\t\tdagc=:ds=:T=\n" - "\t\tport=\n"; +#ifdef WITH_UDP_SERVER + "\t\tport=\n" +#endif + ; else return "\t[-O\tset RTL options string seperated with ':' ]\n"; @@ -3492,6 +3505,7 @@ int rtlsdr_set_opt_string(rtlsdr_dev_t *dev, const char *opts, int verbose) fprintf(stderr, "rtlsdr_set_opt_string(): parsed soft agc dead time %f ms\n", d); dev->softagc.deadTimeMs = d; } +#ifdef WITH_UDP_SERVER else if (!strncmp(optPart, "port=", 5)) { int udpPortNo = atoi(optPart +5); if ( udpPortNo == 1 ) @@ -3500,6 +3514,7 @@ int rtlsdr_set_opt_string(rtlsdr_dev_t *dev, const char *opts, int verbose) fprintf(stderr, "rtlsdr_set_opt_string(): UDP control server port\n", udpPortNo); dev->udpPortNo = udpPortNo; } +#endif else { if (verbose) fprintf(stderr, "rtlsdr_set_opt_string(): parsed unknown option '%s'\n", optPart); @@ -3515,6 +3530,7 @@ int rtlsdr_set_opt_string(rtlsdr_dev_t *dev, const char *opts, int verbose) if ( dev->softagc.agcState != SOFTSTATE_OFF ) softagc_init(dev); +#ifdef WITH_UDP_SERVER if (dev->udpPortNo && dev->srv_started == 0 && dev->tuner_type==RTLSDR_TUNER_R820T) { dev->handled = 1; dev->saved_27 = dev->tuner->get_i2c_register(dev,27); /* highest/lowest corner for LPNF and LPF */ @@ -3527,6 +3543,7 @@ int rtlsdr_set_opt_string(rtlsdr_dev_t *dev, const char *opts, int verbose) fprintf(stderr, "UDP server started on port %u\n", dev->udpPortNo); } } +#endif free(optStr); return retAll; diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c index 728306d..c933306 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -273,9 +273,18 @@ static int r82xx_write_arr(struct r82xx_priv *priv, uint8_t reg, const uint8_t * regOff = pos + k; regIdx = reg - REG_SHADOW_START + regOff; if ( priv->override_mask[regIdx] ) { + uint8_t oldBuf = priv->buf[1 + k]; bufIdx = 1 + k; - priv->buf[bufIdx] = ( priv->buf[bufIdx] & ~ priv->override_mask[regIdx] ) + priv->buf[bufIdx] = ( priv->buf[bufIdx] & (~ priv->override_mask[regIdx]) ) | ( priv->override_mask[regIdx] & priv->override_data[regIdx] ); + fprintf(stderr, "override writing register %d = x%02X value x%02X by data x%02X mask x%02X => new value x%02X\n" + , regIdx + REG_SHADOW_START + , regIdx + REG_SHADOW_START + , oldBuf + , priv->override_data[regIdx] + , priv->override_mask[regIdx] + , priv->buf[bufIdx] + ); } } @@ -1065,7 +1074,7 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain, /* expose/permit tuner specific i2c register hacking! */ -int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsigned mask, unsigned data) +int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsigned data, unsigned mask) { uint8_t reg = i2c_register & 0xFF; uint8_t reg_mask = mask & 0xFF; @@ -1073,22 +1082,43 @@ int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsig return r82xx_write_reg_mask(priv, reg, reg_val, reg_mask); } -int r82xx_set_i2c_override(struct r82xx_priv *priv, unsigned i2c_register, unsigned mask, unsigned data) +int r82xx_set_i2c_override(struct r82xx_priv *priv, unsigned i2c_register, unsigned data, unsigned mask) { uint8_t reg = i2c_register & 0xFF; uint8_t reg_mask = mask & 0xFF; uint8_t reg_val = data & 0xFF; + fprintf(stderr, "%s: register %d = %02X. mask %02X, data %03X\n" + , __FUNCTION__, i2c_register, i2c_register, mask, data ); + if ( REG_SHADOW_START <= reg && reg < REG_SHADOW_START + NUM_REGS ) { + uint8_t oldMask = priv->override_mask[reg - REG_SHADOW_START]; + uint8_t oldData = priv->override_data[reg - REG_SHADOW_START]; if ( data & ~0xFF ) { priv->override_mask[reg - REG_SHADOW_START] &= ~reg_mask; priv->override_data[reg - REG_SHADOW_START] &= ~reg_mask; - fprintf(stderr, "%s: subtracted override mask for register %02X. new mask is %02X\n" - , __FUNCTION__, i2c_register, priv->override_mask[reg - REG_SHADOW_START] ); - } else { + fprintf(stderr, "%s: subtracted override mask for register %02X. old mask %02X, old data %02X. new mask is %02X, new data %02X\n" + , __FUNCTION__ + , i2c_register + , oldMask, oldData + , priv->override_mask[reg - REG_SHADOW_START] + , priv->override_data[reg - REG_SHADOW_START] + ); + } + else + { priv->override_mask[reg - REG_SHADOW_START] |= reg_mask; + priv->override_data[reg - REG_SHADOW_START] &= (~reg_mask); + + fprintf(stderr, "override_data[] &= ( ~(mask %02X) = %02X ) => %02X\n", reg_mask, ~reg_mask, priv->override_data[reg - REG_SHADOW_START] ); priv->override_data[reg - REG_SHADOW_START] |= (reg_mask & reg_val); - fprintf(stderr, "%s: added override mask for register %02X. new mask is %02X\n" - , __FUNCTION__, i2c_register, priv->override_mask[reg - REG_SHADOW_START] ); + fprintf(stderr, "override_data[] |= ( mask %02X & val %02X )\n", reg_mask, reg_val ); + fprintf(stderr, "%s: added override mask for register %d = %02X. old mask %02X, old data %02X. new mask is %02X, new data %02X\n" + , __FUNCTION__ + , i2c_register, i2c_register + , oldMask, oldData + , priv->override_mask[reg - REG_SHADOW_START] + , priv->override_data[reg - REG_SHADOW_START] + ); } return r82xx_write_reg_mask_ext(priv, reg, 0, 0, __FUNCTION__); } @@ -1096,6 +1126,7 @@ int r82xx_set_i2c_override(struct r82xx_priv *priv, unsigned i2c_register, unsig return -1; } + /* Bandwidth contribution by low-pass filter. */ static const int r82xx_if_low_pass_bw_table[] = { 1700000, 1600000, 1550000, 1450000, 1200000, 900000, 700000, 550000, 450000, 350000 @@ -1134,6 +1165,7 @@ int r82xx_set_bandwidth(struct r82xx_priv *priv, int bw, uint32_t rate, uint32_t uint8_t reg_mask; uint8_t reg_0a; uint8_t reg_0b; + uint8_t reg_1e = 0x60; /* default: Enable Filter extension under weak signal */ if (bw > 7000000) { // BW: 8 MHz @@ -1283,6 +1315,22 @@ int r82xx_set_bandwidth(struct r82xx_priv *priv, int bw, uint32_t rate, uint32_t } #endif + /* channel filter extension */ + reg_mask = 0x60; +#if USE_R82XX_ENV_VARS + if ( priv->haveR30H ) { + reg_1e = ( priv->valR30H << 4 ); + } + if ( priv->haveR30L ) { + reg_1e = reg_1e | priv->valR30L; + reg_mask = reg_mask | 0x1F; + } +#endif + rc = r82xx_write_reg_mask_ext(priv, 0x1e, reg_1e, reg_mask, __FUNCTION__); + if (rc < 0) + fprintf(stderr, "%s: ERROR setting I2C register 0x1E to value %02X with mask %02X\n" + , __FUNCTION__, (unsigned)reg_1e, (unsigned)reg_mask); + return priv->int_freq; } #undef FILT_HP_BW1 @@ -1466,6 +1514,8 @@ int r82xx_init(struct r82xx_priv *priv) priv->haveR13H = priv->valR13H = 0; priv->haveR14L = priv->valR14L = 0; priv->haveR14H = priv->valR14H = 0; + priv->haveR30H = priv->valR30H = 0; + priv->haveR30L = priv->valR30L = 0; #endif priv->init_done = 1; @@ -1477,6 +1527,7 @@ int r82xx_init(struct r82xx_priv *priv) char *pacFilterCenter, *pacR9; char *pacR10Hi, *pacR10Lo, *pacR11Hi, *pacR11Lo; char *pacR13Hi, *pacR13Lo, *pacR14Hi, *pacR14Lo; + char *pacR30Hi, *pacR30Lo; pacPrintI2C = getenv("RTL_R820_PRINT_I2C"); if ( pacPrintI2C ) @@ -1586,6 +1637,29 @@ int r82xx_init(struct r82xx_priv *priv) } fprintf(stderr, "*** read R14_LO from environment: %d\n", priv->valR14L); } + + pacR30Hi = getenv("RTL_R820_R30_HI"); + if ( pacR30Hi ) { + priv->haveR30H = 1; + priv->valR30H = atoi(pacR30Hi) & 0x06; + if ( priv->valR30H > 6 || priv->valR30H < 0 ) { + fprintf(stderr, "*** read R30_HI from environment: %d - but value should be 2 - 6 for bit [6:5]\n", priv->valR30H); + priv->haveR30H = 0; + } + fprintf(stderr, "*** read R30_HI from environment: %d\n", priv->valR30H); + } + + pacR30Lo = getenv("RTL_R820_R30_LO"); + if ( pacR30Lo ) { + priv->haveR30L = 1; + priv->valR30L = atoi(pacR30Lo); + if ( priv->valR30L < 0 || priv->valR30L > 31 ) { + fprintf(stderr, "*** read R30_LO from environment: %d - but value should be 0 - 31 for bit [4:0]\n", priv->valR30L); + priv->haveR30L = 0; + } + fprintf(stderr, "*** read R30_LO from environment: %d\n", priv->valR30L); + } + } #endif