Skip to content

Commit 183245f

Browse files
authored
Merge pull request steve-m#9 from rxseger/ir
Add rtl_ir and infrared listening option to rtl_tcp
2 parents bf3319d + a577352 commit 183245f

File tree

7 files changed

+542
-5
lines changed

7 files changed

+542
-5
lines changed

include/rtl-sdr.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,16 @@ RTLSDR_API int rtlsdr_read_async(rtlsdr_dev_t *dev,
404404
*/
405405
RTLSDR_API int rtlsdr_cancel_async(rtlsdr_dev_t *dev);
406406

407+
/*!
408+
* Read from the remote control (RC) infrared (IR) sensor
409+
*
410+
* \param dev the device handle given by rtlsdr_open()
411+
* \param buf buffer to write IR signal (MSB=pulse/space, 7LSB=duration*20usec), recommended 128-bytes
412+
* \param buf_len size of buf
413+
* \return 0 if no signal, >0 number of bytes written into buf, <0 for error
414+
*/
415+
RTLSDR_API int rtlsdr_ir_query(rtlsdr_dev_t *dev, uint8_t *buf, size_t buf_len);
416+
407417
#ifdef __cplusplus
408418
}
409419
#endif

src/CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,11 @@ add_executable(rtl_sdr rtl_sdr.c)
8888
add_executable(rtl_tcp rtl_tcp.c)
8989
add_executable(rtl_test rtl_test.c)
9090
add_executable(rtl_fm rtl_fm.c)
91+
add_executable(rtl_ir rtl_ir.c)
9192
add_executable(rtl_eeprom rtl_eeprom.c)
9293
add_executable(rtl_adsb rtl_adsb.c)
9394
add_executable(rtl_power rtl_power.c)
94-
set(INSTALL_TARGETS rtlsdr_shared rtlsdr_static rtl_sdr rtl_tcp rtl_test rtl_fm rtl_eeprom rtl_adsb rtl_power)
95+
set(INSTALL_TARGETS rtlsdr_shared rtlsdr_static rtl_sdr rtl_tcp rtl_test rtl_fm rtl_ir rtl_eeprom rtl_adsb rtl_power)
9596

9697
target_link_libraries(rtl_sdr rtlsdr_shared convenience_static
9798
${LIBUSB_LIBRARIES}
@@ -109,6 +110,10 @@ target_link_libraries(rtl_fm rtlsdr_shared convenience_static
109110
${LIBUSB_LIBRARIES}
110111
${CMAKE_THREAD_LIBS_INIT}
111112
)
113+
target_link_libraries(rtl_ir rtlsdr_shared convenience_static
114+
${LIBUSB_LIBRARIES}
115+
${CMAKE_THREAD_LIBS_INIT}
116+
)
112117
target_link_libraries(rtl_eeprom rtlsdr_shared convenience_static
113118
${LIBUSB_LIBRARIES}
114119
${CMAKE_THREAD_LIBS_INIT}
@@ -123,6 +128,7 @@ target_link_libraries(rtl_power rtlsdr_shared convenience_static
123128
)
124129
if(UNIX)
125130
target_link_libraries(rtl_fm m)
131+
target_link_libraries(rtl_ir m)
126132
target_link_libraries(rtl_adsb m)
127133
target_link_libraries(rtl_power m)
128134
if(APPLE)
@@ -137,13 +143,15 @@ target_link_libraries(rtl_sdr libgetopt_static)
137143
target_link_libraries(rtl_tcp ws2_32 libgetopt_static)
138144
target_link_libraries(rtl_test libgetopt_static)
139145
target_link_libraries(rtl_fm libgetopt_static)
146+
target_link_libraries(rtl_ir libgetopt_static)
140147
target_link_libraries(rtl_eeprom libgetopt_static)
141148
target_link_libraries(rtl_adsb libgetopt_static)
142149
target_link_libraries(rtl_power libgetopt_static)
143150
set_property(TARGET rtl_sdr APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" )
144151
set_property(TARGET rtl_tcp APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" )
145152
set_property(TARGET rtl_test APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" )
146153
set_property(TARGET rtl_fm APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" )
154+
set_property(TARGET rtl_ir APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" )
147155
set_property(TARGET rtl_eeprom APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" )
148156
set_property(TARGET rtl_adsb APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" )
149157
set_property(TARGET rtl_power APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" )

src/Makefile.am

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ lib_LTLIBRARIES = librtlsdr.la
1212
librtlsdr_la_SOURCES = librtlsdr.c tuner_e4k.c tuner_fc0012.c tuner_fc0013.c tuner_fc2580.c tuner_r82xx.c
1313
librtlsdr_la_LDFLAGS = -version-info $(LIBVERSION)
1414

15-
bin_PROGRAMS = rtl_sdr rtl_tcp rtl_test rtl_fm rtl_eeprom rtl_adsb rtl_power
15+
bin_PROGRAMS = rtl_sdr rtl_tcp rtl_test rtl_fm rtl_ir rtl_eeprom rtl_adsb rtl_power
1616

1717
rtl_sdr_SOURCES = rtl_sdr.c convenience/convenience.c
1818
rtl_sdr_LDADD = librtlsdr.la
@@ -26,6 +26,9 @@ rtl_test_LDADD = librtlsdr.la $(LIBM)
2626
rtl_fm_SOURCES = rtl_fm.c convenience/convenience.c
2727
rtl_fm_LDADD = librtlsdr.la $(LIBM)
2828

29+
rtl_ir_SOURCES = rtl_ir.c convenience/convenience.c
30+
rtl_ir_LDADD = librtlsdr.la $(LIBM)
31+
2932
rtl_eeprom_SOURCES = rtl_eeprom.c convenience/convenience.c
3033
rtl_eeprom_LDADD = librtlsdr.la $(LIBM)
3134

src/librtlsdr.c

Lines changed: 208 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ struct rtlsdr_dev {
124124
int dev_lost;
125125
int driver_active;
126126
unsigned int xfer_errors;
127+
int rc_active;
127128
};
128129

129130
void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val);
@@ -407,6 +408,51 @@ enum sys_reg {
407408
SYSINTS_1 = 0x300a,
408409
DEMOD_CTL_1 = 0x300b,
409410
IR_SUSPEND = 0x300c,
411+
412+
/* IrDA registers */
413+
SYS_IRRC_PSR = 0x3020, /* IR protocol selection */
414+
SYS_IRRC_PER = 0x3024, /* IR protocol extension */
415+
SYS_IRRC_SF = 0x3028, /* IR sampling frequency */
416+
SYS_IRRC_DPIR = 0x302C, /* IR data package interval */
417+
SYS_IRRC_CR = 0x3030, /* IR control */
418+
SYS_IRRC_RP = 0x3034, /* IR read port */
419+
SYS_IRRC_SR = 0x3038, /* IR status */
420+
/* I2C master registers */
421+
SYS_I2CCR = 0x3040, /* I2C clock */
422+
SYS_I2CMCR = 0x3044, /* I2C master control */
423+
SYS_I2CMSTR = 0x3048, /* I2C master SCL timing */
424+
SYS_I2CMSR = 0x304C, /* I2C master status */
425+
SYS_I2CMFR = 0x3050, /* I2C master FIFO */
426+
427+
/*
428+
* IR registers
429+
*/
430+
IR_RX_BUF = 0xFC00,
431+
IR_RX_IE = 0xFD00,
432+
IR_RX_IF = 0xFD01,
433+
IR_RX_CTRL = 0xFD02,
434+
IR_RX_CFG = 0xFD03,
435+
IR_MAX_DURATION0 = 0xFD04,
436+
IR_MAX_DURATION1 = 0xFD05,
437+
IR_IDLE_LEN0 = 0xFD06,
438+
IR_IDLE_LEN1 = 0xFD07,
439+
IR_GLITCH_LEN = 0xFD08,
440+
IR_RX_BUF_CTRL = 0xFD09,
441+
IR_RX_BUF_DATA = 0xFD0A,
442+
IR_RX_BC = 0xFD0B,
443+
IR_RX_CLK = 0xFD0C,
444+
IR_RX_C_COUNT_L = 0xFD0D,
445+
IR_RX_C_COUNT_H = 0xFD0E,
446+
IR_SUSPEND_CTRL = 0xFD10,
447+
IR_ERR_TOL_CTRL = 0xFD11,
448+
IR_UNIT_LEN = 0xFD12,
449+
IR_ERR_TOL_LEN = 0xFD13,
450+
IR_MAX_H_TOL_LEN = 0xFD14,
451+
IR_MAX_L_TOL_LEN = 0xFD15,
452+
IR_MASK_CTRL = 0xFD16,
453+
IR_MASK_DATA = 0xFD17,
454+
IR_RES_MASK_ADDR = 0xFD18,
455+
IR_RES_MASK_T_LEN = 0xFD19,
410456
};
411457

412458
enum blocks {
@@ -423,6 +469,7 @@ int rtlsdr_read_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t *
423469
{
424470
int r;
425471
uint16_t index = (block << 8);
472+
if (block == IRB) index = (SYSB << 8) | 0x01;
426473

427474
r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, array, len, CTRL_TIMEOUT);
428475
#if 0
@@ -436,6 +483,7 @@ int rtlsdr_write_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t
436483
{
437484
int r;
438485
uint16_t index = (block << 8) | 0x10;
486+
if (block == IRB) index = (SYSB << 8) | 0x11;
439487

440488
r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, array, len, CTRL_TIMEOUT);
441489
#if 0
@@ -490,8 +538,9 @@ uint16_t rtlsdr_read_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_
490538
{
491539
int r;
492540
unsigned char data[2];
493-
uint16_t index = (block << 8);
494541
uint16_t reg;
542+
uint16_t index = (block << 8);
543+
if (block == IRB) index = (SYSB << 8) | 0x01;
495544

496545
r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT);
497546

@@ -509,6 +558,7 @@ int rtlsdr_write_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint16_t v
509558
unsigned char data[2];
510559

511560
uint16_t index = (block << 8) | 0x10;
561+
if (block == IRB) index = (SYSB << 8) | 0x11;
512562

513563
if (len == 1)
514564
data[0] = val & 0xff;
@@ -1992,3 +2042,160 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
19922042

19932043
return -1;
19942044
}
2045+
2046+
2047+
/* Infrared (IR) sensor support
2048+
* based on Linux dvb_usb_rtl28xxu drivers/media/usb/dvb-usb-v2/rtl28xxu.h
2049+
* Copyright (C) 2009 Antti Palosaari <[email protected]>
2050+
* Copyright (C) 2011 Antti Palosaari <[email protected]>
2051+
* Copyright (C) 2012 Thomas Mair <[email protected]>
2052+
*/
2053+
2054+
struct rtl28xxu_req {
2055+
uint16_t value;
2056+
uint16_t index;
2057+
uint16_t size;
2058+
uint8_t *data;
2059+
};
2060+
2061+
struct rtl28xxu_reg_val {
2062+
uint16_t reg;
2063+
uint8_t val;
2064+
};
2065+
2066+
struct rtl28xxu_reg_val_mask {
2067+
int block;
2068+
uint16_t reg;
2069+
uint8_t val;
2070+
uint8_t mask;
2071+
};
2072+
2073+
static int rtlsdr_read_regs(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t *data, uint8_t len)
2074+
{
2075+
int r;
2076+
uint16_t index = (block << 8);
2077+
if (block == IRB) index = (SYSB << 8) | 0x01;
2078+
2079+
r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT);
2080+
2081+
if (r < 0)
2082+
fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r);
2083+
2084+
return r;
2085+
}
2086+
2087+
static int rtlsdr_write_reg_mask(rtlsdr_dev_t *d, int block, uint16_t reg, uint8_t val,
2088+
uint8_t mask)
2089+
{
2090+
int ret;
2091+
uint8_t tmp;
2092+
2093+
/* no need for read if whole reg is written */
2094+
if (mask != 0xff) {
2095+
tmp = rtlsdr_read_reg(d, block, reg, 1);
2096+
2097+
val &= mask;
2098+
tmp &= ~mask;
2099+
val |= tmp;
2100+
}
2101+
2102+
return rtlsdr_write_reg(d, block, reg, (uint16_t)val, 1);
2103+
}
2104+
2105+
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
2106+
2107+
int rtlsdr_ir_query(rtlsdr_dev_t *d, uint8_t *buf, size_t buf_len)
2108+
{
2109+
int ret = -1;
2110+
size_t i, len;
2111+
static const struct rtl28xxu_reg_val_mask refresh_tab[] = {
2112+
{IRB, IR_RX_IF, 0x03, 0xff},
2113+
{IRB, IR_RX_BUF_CTRL, 0x80, 0xff},
2114+
{IRB, IR_RX_CTRL, 0x80, 0xff},
2115+
};
2116+
2117+
/* init remote controller */
2118+
if (!d->rc_active) {
2119+
//fprintf(stderr, "initializing remote controller\n");
2120+
static const struct rtl28xxu_reg_val_mask init_tab[] = {
2121+
{USBB, DEMOD_CTL, 0x00, 0x04},
2122+
{USBB, DEMOD_CTL, 0x00, 0x08},
2123+
{USBB, USB_CTRL, 0x20, 0x20},
2124+
{USBB, GPD, 0x00, 0x08},
2125+
{USBB, GPOE, 0x08, 0x08},
2126+
{USBB, GPO, 0x08, 0x08},
2127+
{IRB, IR_MAX_DURATION0, 0xd0, 0xff},
2128+
{IRB, IR_MAX_DURATION1, 0x07, 0xff},
2129+
{IRB, IR_IDLE_LEN0, 0xc0, 0xff},
2130+
{IRB, IR_IDLE_LEN1, 0x00, 0xff},
2131+
{IRB, IR_GLITCH_LEN, 0x03, 0xff},
2132+
{IRB, IR_RX_CLK, 0x09, 0xff},
2133+
{IRB, IR_RX_CFG, 0x1c, 0xff},
2134+
{IRB, IR_MAX_H_TOL_LEN, 0x1e, 0xff},
2135+
{IRB, IR_MAX_L_TOL_LEN, 0x1e, 0xff},
2136+
{IRB, IR_RX_CTRL, 0x80, 0xff},
2137+
};
2138+
2139+
for (i = 0; i < ARRAY_SIZE(init_tab); i++) {
2140+
ret = rtlsdr_write_reg_mask(d, init_tab[i].block, init_tab[i].reg,
2141+
init_tab[i].val, init_tab[i].mask);
2142+
if (ret < 0) {
2143+
fprintf(stderr, "write %d reg %d %.4x %.2x %.2x failed\n", i, init_tab[i].block,
2144+
init_tab[i].reg, init_tab[i].val, init_tab[i].mask);
2145+
goto err;
2146+
}
2147+
}
2148+
2149+
d->rc_active = 1;
2150+
//fprintf(stderr, "rc active\n");
2151+
}
2152+
// TODO: option to ir disable
2153+
2154+
buf[0] = rtlsdr_read_reg(d, IRB, IR_RX_IF, 1);
2155+
2156+
if (buf[0] != 0x83) {
2157+
if (buf[0] == 0 || // no IR signal
2158+
// also observed: 0x82, 0x81 - with lengths 1, 5, 0.. unknown, sometimes occurs at edges
2159+
// "IR not ready"? causes a -7 timeout if we read
2160+
buf[0] == 0x82 || buf[0] == 0x81) {
2161+
// graceful exit
2162+
} else {
2163+
fprintf(stderr, "read IR_RX_IF unexpected: %.2x\n", buf[0]);
2164+
}
2165+
2166+
ret = 0;
2167+
goto exit;
2168+
}
2169+
2170+
buf[0] = rtlsdr_read_reg(d, IRB, IR_RX_BC, 1);
2171+
2172+
len = buf[0];
2173+
//fprintf(stderr, "read IR_RX_BC len=%d\n", len);
2174+
2175+
if (len > buf_len) {
2176+
//fprintf(stderr, "read IR_RX_BC too large for buffer, %lu > %lu\n", buf_len, buf_len);
2177+
goto exit;
2178+
}
2179+
2180+
/* read raw code from hw */
2181+
ret = rtlsdr_read_regs(d, IRB, IR_RX_BUF, buf, len);
2182+
if (ret < 0)
2183+
goto err;
2184+
2185+
/* let hw receive new code */
2186+
for (i = 0; i < ARRAY_SIZE(refresh_tab); i++) {
2187+
ret = rtlsdr_write_reg_mask(d, refresh_tab[i].block, refresh_tab[i].reg,
2188+
refresh_tab[i].val, refresh_tab[i].mask);
2189+
if (ret < 0)
2190+
goto err;
2191+
}
2192+
2193+
// On success return length
2194+
ret = len;
2195+
2196+
exit:
2197+
return ret;
2198+
err:
2199+
printf("failed=%d\n", ret);
2200+
return ret;
2201+
}

src/rtl_fm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ int polar_disc_lut(int ar, int aj, int br, int bj)
548548

549549
if (x_abs >= atan_lut_size) {
550550
/* we can use linear range, but it is not necessary */
551-
return (cj > 0) ? 1<<13 : -1<<13;
551+
return (cj > 0) ? 1<<13 : -(1<<13);
552552
}
553553

554554
if (x > 0) {

0 commit comments

Comments
 (0)