From 2825bdf9a46bc1251a647b2b48d6edfb9a151af4 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Sun, 23 Jun 2013 14:23:05 +0100 Subject: [PATCH] linuxdvb: added rotor GOTOX/USALS implementation This is taken from PR #238. I still don't have the movement duration stuff done. And now I really need to think more about the config. --- src/input/mpegts/linuxdvb/linuxdvb_rotor.c | 192 ++++++++++++++++++- src/input/mpegts/linuxdvb/linuxdvb_satconf.c | 6 + 2 files changed, 191 insertions(+), 7 deletions(-) diff --git a/src/input/mpegts/linuxdvb/linuxdvb_rotor.c b/src/input/mpegts/linuxdvb/linuxdvb_rotor.c index d5999bb2..3f5e2a96 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_rotor.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_rotor.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include /* ************************************************************************** * Class definition @@ -39,18 +39,98 @@ typedef struct linuxdvb_rotor { linuxdvb_diseqc_t; - /* Port settings */ - int ls_toneburst; - int ls_committed; - int ls_uncomitted; + enum { + ROTOR_GOTOX, + ROTOR_USALS + } lr_type; + + double lr_site_lat; + double lr_site_lon; + double lr_sat_lon; + + uint32_t lr_position; + + uint32_t lr_rate; } linuxdvb_rotor_t; +static const void * +linuxdvb_rotor_class_type_get ( void *o ) +{ + static const char *str; + linuxdvb_rotor_t *lr = o; + str = lr->lr_type == ROTOR_GOTOX ? "GOTOX" : "USALS"; + return &str; +} + +static int +linuxdvb_rotor_class_type_set ( void *o, const void *p ) +{ + const char *str = p; + linuxdvb_rotor_t *lr = o; + if (!strcmp("GOTOX", str)) + lr->lr_type = ROTOR_GOTOX; + else + lr->lr_type = ROTOR_USALS; + return 1; +} + +static htsmsg_t * +linuxdvb_rotor_class_type_list ( void *o ) +{ + htsmsg_t *m = htsmsg_create_list(); + htsmsg_add_str(m, NULL, "GOTOX"); + htsmsg_add_str(m, NULL, "USALS"); + return m; +} + const idclass_t linuxdvb_rotor_class = { .ic_class = "linuxdvb_switch", .ic_caption = "DiseqC switch", .ic_properties = (const property_t[]) { + { + .type = PT_STR, + .id = "type", + .name = "Rotor Type", + .get = linuxdvb_rotor_class_type_get, + .set = linuxdvb_rotor_class_type_set, + .list = linuxdvb_rotor_class_type_list, + }, +#if 0 + { + .type = PT_DBL, + .id = "site_lat", + .name = "Site Lat", + .off = offsetof(linuxdvb_rotor_t, lr_site_lat), + }, + { + .type = PT_DBL, + .id = "site_lon", + .name = "Site Lon", + .off = offsetof(linuxdvb_rotor_t, lr_site_lon), + }, + { + .type = PT_DBL, + .id = "sat_lon", + .name = "Sat Lon", + .off = offsetof(linuxdvb_rotor_t, lr_sat_lon), + }, +#endif + { + .type = PT_U16, + .id = "position", + .name = "Position", + .off = offsetof(linuxdvb_rotor_t, lr_site_lat), + }, + { + .type = PT_U16, + .id = "rate", + .name = "Rate (millis/deg)", + .off = offsetof(linuxdvb_rotor_t, lr_rate), + }, + { + } } }; @@ -58,11 +138,108 @@ const idclass_t linuxdvb_rotor_class = * Class methods * *************************************************************************/ +/* GotoX */ +static int +linuxdvb_rotor_gotox_tune + ( linuxdvb_rotor_t *lr, linuxdvb_mux_t *lm, int fd ) +{ + if (diseqc_send_msg(fd, 0xE0, 0x31, 0x6B, lr->lr_position, 0, 0, 4)) { + tvherror("linuxdvb", "failed to set GOTOX pos %d", lr->lr_position); + return -1; + } + + tvhdebug("linuxdvb", "rotor GOTOX pos %d sent", lr->lr_position); + return 120; // TODO: calculate period (2 min hardcoded) +} + +/* USALS */ +static int +linuxdvb_rotor_usals_tune + ( linuxdvb_rotor_t *lr, linuxdvb_mux_t *lm, int fd ) +{ + /* + * Code originally written in PR #238 by Jason Millard jsm174 + * + * USALS rotor logic adapted from tune-s2 + * http://updatelee.blogspot.com/2010/09/tune-s2.html + * + * Antenna Alignment message data format: + * http://www.dvb.org/technology/standards/A155-3_DVB-RCS2_Higher_layer_satellite_spec.pdf + */ + +#define TO_DEG(x) ((x * 180.0) / M_PI) +#define TO_RAD(x) ((x * M_PI) / 180.0) + + static const double r_eq = 6378.14; + static const double r_sat = 42164.57; + + double lat = TO_RAD(lr->lr_site_lat); + double lon = TO_RAD(lr->lr_site_lon); + double pos = TO_RAD(lr->lr_sat_lon); + + double dishVector[3] = { + (r_eq * cos(lat)), + 0, + (r_eq * sin(lat)), + }; + + double satVector[3] = { + (r_sat * cos(lon - pos)), + (r_sat * sin(lon - pos)), + 0 + }; + + double satPointing[3] = { + (satVector[0] - dishVector[0]), + (satVector[1] - dishVector[1]), + (satVector[2] - dishVector[2]) + }; + + double motor_angle = TO_DEG(atan(satPointing[1] / satPointing[0])); + + int sixteenths = ((fabs(motor_angle) * 16.0) + 0.5); + + int angle_1 = (((motor_angle > 0.0) ? 0xd0 : 0xe0) | (sixteenths >> 8)); + int angle_2 = (sixteenths & 0xff); + + tvhtrace("linuxdvb", "rotor USALS goto %0.1f%c (motor %0.2f %sclockwise)", + fabs(pos), (pos > 0.0) ? 'E' : 'W', + motor_angle, (motor_angle > 0.0) ? "counter-" : ""); + + if (diseqc_send_msg(fd, 0xE0, 0x31, 0x6E, angle_1, angle_2, 0, 5)) { + tvherror("linuxdvb", "failed to send USALS command"); + return -1; + } + + return 120; // TODO: calculate period (2 min hardcoded) +} + static int linuxdvb_rotor_tune ( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm, int fd ) { - return 0; + linuxdvb_rotor_t *lr = (linuxdvb_rotor_t*)ld; + + /* Force to 18v (quicker movement) */ + if (ioctl(fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18)) { + tvherror("linuxdvb", "failed to set 18v for rotor movement"); + return -1; + } + usleep(15000); + + /* GotoX */ + if (lr->lr_type == ROTOR_GOTOX) + return linuxdvb_rotor_gotox_tune(lr, lm, fd); + + /* USALS */ + return linuxdvb_rotor_usals_tune(lr, lm, fd); +} + +static int +linuxdvb_rotor_grace + ( linuxdvb_diseqc_t *ld, linuxdvb_mux_t *lm ) +{ + return 120; // TODO: calculate approx period } /* ************************************************************************** @@ -76,7 +253,8 @@ linuxdvb_rotor_create0 linuxdvb_diseqc_t *ld = linuxdvb_diseqc_create(linuxdvb_rotor, NULL, conf); if (ld) { - ld->ld_tune = linuxdvb_rotor_tune; + ld->ld_tune = linuxdvb_rotor_tune; + ld->ld_grace = linuxdvb_rotor_grace; } return ld; diff --git a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c index b52e34bf..8797c9f8 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_satconf.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_satconf.c @@ -252,6 +252,12 @@ linuxdvb_satconf_tune ( linuxdvb_satconf_t *ls ) (linuxdvb_diseqc_t*)ls->ls_lnb }; + /* Disable tone */ + if (ioctl(lfe->lfe_fe_fd, FE_SET_TONE, SEC_TONE_OFF)) { + tvherror("linuxdvb", "failed to disable tone"); + return -1; + } + /* Diseqc */ i = ls->ls_diseqc_idx; for (i = ls->ls_diseqc_idx; i < 3; i++) {