[PATCH] scan-s2: fixes and diseqc rotor support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I have attached two patches for scan-s2 at http://mercurial.intuxication.org/hg/scan-s2.

Patch1: Some fixes for problems I found. QAM_AUTO is not supported by all drivers,
in particular the HVR-4000, so one needs to use QPSK as the default and ensure that
settings are parsed properly from the network information -- the new S2 FECs and
modulations were not handled.

Patch2: Add DiSEqC 1.2 rotor support. Use it like this to move the dish to the correct
position for the scan:
 scan-s2 -r 19.2E -n dvb-s/Astra-19.2E
 or
 scan-s2 -R 2 -n dvb-s/Astra-19.2E

A file (rotor.conf) listing the rotor positions is used (NB: rotors vary -- do check your
rotor manual).

Regards,
Hans

-- 
Release early, release often.

Ist Ihr Browser Vista-kompatibel? Jetzt die neuesten 
Browser-Versionen downloaden: http://www.gmx.net/de/go/browser
diff -r 40368fdba59a scan.c
--- a/scan.c
+++ b/scan.c
@@ -393,25 +397,32 @@ static void parse_s2_satellite_delivery_
 
 static void parse_satellite_delivery_system_descriptor (const unsigned char *buf, struct transponder *t)
 {
-	static const fe_code_rate_t fec_tab [8] = {
-		FEC_AUTO, FEC_1_2, FEC_2_3, FEC_3_4,
-		FEC_5_6, FEC_7_8, FEC_NONE, FEC_NONE
-	};
-
 	if (!t) {
 		warning("satellite_delivery_system_descriptor outside transport stream definition (ignored)\n");
 		return;
 	}
 
-	if(((buf[8] >> 1) & 0x01) == 0) {
-		t->delivery_system = SYS_DVBS;
-	}
-	else {
-		t->delivery_system = SYS_DVBS2;
+	switch ( getBits(buf,69,1) ) {
+		case 0: t->delivery_system = SYS_DVBS; break;
+		case 1: t->delivery_system = SYS_DVBS2; break;
 	}
 
 	t->frequency = 10 * bcd32_to_cpu (buf[2], buf[3], buf[4], buf[5]);
-	t->fec = fec_tab[buf[12] & 0x07];
+	
+	switch ( getBits(buf,100,4) ) {
+                case 0 : t->fec = FEC_AUTO; break;
+                case 1 : t->fec = FEC_1_2; break;
+                case 2 : t->fec = FEC_2_3; break;
+                case 3 : t->fec = FEC_3_4; break;
+                case 4 : t->fec = FEC_5_6; break;
+                case 5 : t->fec = FEC_7_8; break;
+                case 6 : t->fec = FEC_8_9; break;
+                case 7 : t->fec = FEC_3_5; break;
+                case 8 : t->fec = FEC_4_5; break;
+                case 9 : t->fec = FEC_9_10; break;
+                case 15 : t->fec = FEC_NONE; break;
+        }
+	
 	t->symbol_rate = 10 * bcd32_to_cpu (buf[9], buf[10], buf[11], buf[12] & 0xf0);
 
 	t->inversion = spectral_inversion;	
@@ -419,6 +430,13 @@ static void parse_satellite_delivery_sys
 	t->polarisation = (buf[8] >> 5) & 0x03;
 	t->orbital_pos = bcd32_to_cpu (0x00, 0x00, buf[6], buf[7]);
 	t->we_flag = buf[8] >> 7;
+
+	switch ( getBits(buf,70,2) ) {
+                case 0 : t->modulation = QAM_AUTO; break;
+                case 1 : t->modulation = QPSK; break;
+                case 2 : t->modulation = PSK_8; break;
+                case 3 : t->modulation = QAM_16; break;
+        }
 
 	if (verbosity >= 5) {
 		debug("%#04x/%#04x ", t->network_id, t->transport_stream_id);
@@ -1858,7 +1892,7 @@ struct strtab qamtab[] = {
 
 static enum fe_modulation str2qam(const char *qam)
 {
-	return str2enum(qam, qamtab, QAM_AUTO);
+	return str2enum(qam, qamtab, QPSK);
 }
 
 static const char* qam2str(enum fe_modulation qam)
@@ -1968,8 +2074,8 @@ static int tune_initial (int frontend_fd
 		else if (sscanf(buf, "S %u %1[HVLR] %u %4s %4s %6s\n", &f, pol, &sr, fec, rolloff, qam) >= 3) {
 			t = alloc_transponder(f);
 			t->delivery_system = SYS_DVBS;
-			t->modulation = QAM_AUTO;
-			t->rolloff = ROLLOFF_AUTO;
+			t->modulation = QPSK;
+			t->rolloff = ROLLOFF_35;
 			t->fec = FEC_AUTO;
 			switch(pol[0]) 
 			{
diff -r 40368fdba59a diseqc.c
--- a/diseqc.c
+++ b/diseqc.c
@@ -45,6 +45,77 @@ struct diseqc_cmd uncommitted_switch_cmd
 };
 
 /*--------------------------------------------------------------------------*/
+
+#define DISEQC_X 2
+int rotor_command( int frontend_fd, int cmd, int n1, int n2, int n3 )
+{
+	int err;
+        struct dvb_diseqc_master_cmd cmds[] = {
+                { { 0xe0, 0x31, 0x60, 0x00, 0x00, 0x00 }, 3 },  //0 Stop Positioner movement
+                { { 0xe0, 0x31, 0x63, 0x00, 0x00, 0x00 }, 3 },  //1 Disable Limits
+                { { 0xe0, 0x31, 0x66, 0x00, 0x00, 0x00 }, 3 },  //2 Set East Limit
+                { { 0xe0, 0x31, 0x67, 0x00, 0x00, 0x00 }, 3 },  //3 Set West Limit
+                { { 0xe0, 0x31, 0x68, 0x00, 0x00, 0x00 }, 4 },  //4 Drive Motor East continously
+                { { 0xe0, 0x31, 0x68,256-n1,0x00, 0x00 }, 4 },  //5 Drive Motor East nn steps
+                { { 0xe0, 0x31, 0x69,256-n1,0x00, 0x00 }, 4 },  //6 Drive Motor West nn steps
+                { { 0xe0, 0x31, 0x69, 0x00, 0x00, 0x00 }, 4 },  //7 Drive Motor West continously
+                { { 0xe0, 0x31, 0x6a, n1, 0x00, 0x00 }, 4 },  //8 Store nn
+                { { 0xe0, 0x31, 0x6b, n1, 0x00, 0x00 }, 4 },   //9 Goto nn
+                { { 0xe0, 0x31, 0x6f, n1, n2, n3 }, 4}, //10 Recalculate Position
+                { { 0xe0, 0x31, 0x6a, 0x00, 0x00, 0x00 }, 4 },  //11 Enable Limits
+                { { 0xe0, 0x31, 0x6e, n1, n2, 0x00 }, 5 },   //12 Gotoxx
+                { { 0xe0, 0x10, 0x38, 0xF4, 0x00, 0x00 }, 4 }    //13 User
+        };
+
+        int i;
+        for ( i=0; i<DISEQC_X; ++i ) {
+                usleep(15*1000);
+                if ( err = ioctl( frontend_fd, FE_DISEQC_SEND_MASTER_CMD, &cmds[cmd] ) )
+                        error("rotor_command: FE_DISEQC_SEND_MASTER_CMD failed, err=%i\n",err);
+        }
+	return err;
+}
+
+int rotate_rotor (int frontend_fd, int from_rotor_pos, int to_rotor_pos, int voltage_18){
+	/* Rotate a DiSEqC 1.2 rotor from position from_rotor_pos to position to_rotor_pos */
+	/* Uses Goto nn (command 9) */
+	float rotor_wait_time; //seconds
+	int err=0;
+
+	float speed_13V = 1.5; //degrees per second
+	float speed_18V = 2.4; //degrees per second
+	float degreesmoved,a1,a2;
+
+	if (to_rotor_pos != 0) {
+		if (from_rotor_pos != to_rotor_pos) {
+			info("Moving rotor from position %i to position %i\n",from_rotor_pos,to_rotor_pos);
+			if (from_rotor_pos == 0) {
+				rotor_wait_time = 15; // starting from unknown position
+			} else {
+				a1 = rotor_angle(to_rotor_pos);
+				a2 = rotor_angle(from_rotor_pos);
+				degreesmoved = abs(a1-a2);
+				if (degreesmoved>180) degreesmoved=360-degreesmoved;
+				rotor_wait_time = degreesmoved / (voltage_18 ? speed_18V : speed_13V);
+			}
+			err = rotor_command(frontend_fd, 9, to_rotor_pos, 0, 0);
+			if (err) {
+				info("Rotor move error!\n");
+			} else {
+				int i;
+				info("Rotating");
+				for (i=0; i<10; i++){
+					usleep(rotor_wait_time*100000);
+					info(".");
+				}
+				info("completed.\n");
+			}
+		} else {
+			info("Rotor already at position %i\n", from_rotor_pos);
+		}
+	}
+	return err;
+}
 
 static inline void msleep(uint32_t msec)
 {
diff -r 40368fdba59a diseqc.h
--- a/diseqc.h
+++ b/diseqc.h
@@ -17,6 +17,7 @@ extern int diseqc_send_msg (int fd, fe_s
 *   set up the switch to position/voltage/tone
 */
 extern int setup_switch (int frontend_fd, int switch_pos, int voltage_18, int freq, int uncommitted_switch_pos);
+extern int rotate_rotor (int frontend_fd, int from_rotor_pos, int to_rotor_pos, int voltage_18);
 
 
 #endif
diff -r 40368fdba59a scan.c
--- a/scan.c
+++ b/scan.c
@@ -84,10 +84,14 @@ static fe_spectral_inversion_t spectral_
 static fe_spectral_inversion_t spectral_inversion = INVERSION_AUTO;
 static int switch_pos = 0;
 static int uncommitted_switch_pos = 0;
+static int rotor_pos = 0;
+static int curr_rotor_pos = 0;
+static char rotor_pos_name[16] = "";
 static char override_orbital_pos[16] = "";
 static enum format output_format = OUTPUT_VDR;
 static int output_format_set = 0;
 
+static rotorslot_t rotor[49];
 
 struct section_buf {
 	struct list_head list;
@@ -1569,6 +1587,22 @@ static int __tune_to_transponder (int fr
 		if (verbosity >= 2) {
 			dprintf(1,"DVB-S IF freq is %d\n", if_freq);
 		}
+
+		
+		if (rotor_pos != 0 ) {
+			/* Rotate DiSEqC 1.2 rotor to correct orbital position */
+			if (t->orbital_pos!=0) rotor_pos = rotor_nn(t->orbital_pos, t->we_flag);
+			int err;
+			err = rotate_rotor(	frontend_fd,
+						curr_rotor_pos, 
+						rotor_pos,
+						t->polarisation == POLARISATION_VERTICAL ? 0 : 1);
+			if (err)
+				error("Error in rotate_rotor err=%i\n",err); 
+			else
+				curr_rotor_pos = rotor_pos;
+		}
+
 		break;
 
 	case SYS_DVBT:
@@ -1939,6 +1973,78 @@ static const char* hier2str(enum fe_hier
 	return enum2str(hier, hiertab, "???");
 }
 
+static int read_rotor_conf(const char *rotor_conf)
+{
+	FILE *rotor_conf_fd;
+	unsigned int nn;
+	char buf[200], angle_we[20], angle[20], we[2];
+	int i = -1;
+	rotor_conf_fd = fopen (rotor_conf, "r");
+	if (!rotor_conf_fd){
+		error("Cannot open rotor configuration file '%s'.");
+		return errno;
+	}
+	while (fgets(buf, sizeof(buf), rotor_conf_fd)) {
+		if (buf[0] != '#' && buf[0] != '\n') {
+			if (sscanf(buf, "%u %s\n", &nn, angle_we)==2) {
+				i++;
+				rotor[i].nn = nn;
+				strcpy(rotor[i].angle_we,angle_we);
+				strncpy(angle,angle_we,strlen(angle_we)-1);
+				rotor[i].orbital_pos = atof(angle) * 10;
+				strncpy(we,angle_we+strlen(angle_we)-1,1);
+				we[1]='\0';
+				rotor[i].we_flag = (strcmp(we,"W")==0 || strcmp(we,"w")==0) ? 0 : 1;
+				//info("rotor: i=%i, nn=%i, orbital_pos=%i we_flag=%i\n", 
+				//	i, rotor[i].nn, rotor[i].orbital_pos, rotor[i].we_flag);
+			}
+		}
+	}
+	fclose(rotor_conf_fd);
+	return 0;
+}
+
+int rotor_nn(int orbital_pos, int we_flag){
+	/*given say 192,1 return the position number*/
+	int i;
+	for (i=0; i<49; i++){
+		if (rotor[i].orbital_pos == orbital_pos && rotor[i].we_flag == we_flag) {
+			return rotor[i].nn;
+		}
+	}
+	error("rotor_nn: orbital_pos=%i, we_flag=%i not found.\n", orbital_pos, we_flag);
+	return 0;
+}
+
+int rotor_name2nn(char *angle_we){
+	/*given say '19.2E' return the position number*/
+	int i;
+	for (i=0; i<49; i++){
+		if (strcmp(rotor[i].angle_we, angle_we) == 0) {
+			return rotor[i].nn;
+		}
+	}
+	error("rotor_name2nn: '%s' not found.\n", angle_we);
+	return 0;
+}
+
+float rotor_angle(int nn) {
+	/*given nn, return the angle in 0.0-359.9 range (1=1.0E, 359=1.0W) */
+	int i;
+	float angle;
+	for (i=0; i<49; i++){
+		if (rotor[i].nn == nn) {
+			if(rotor[i].we_flag == 0) //west
+				angle = 360.00 - rotor[i].orbital_pos / 10;
+			else //east
+				angle = rotor[i].orbital_pos / 10;
+			return angle;
+		}
+	}
+	error("rotor_angle: nn=%i not found",nn);
+	return -999;
+}
+
 static int tune_initial (int frontend_fd, const char *initial)
 {
 	FILE *inif;
@@ -2353,6 +2459,8 @@ static const char *usage = "\n"
 "	-d N	use DVB /dev/dvb/adapter?/demuxN\n"
 "	-s N	use DiSEqC switch position N (DVB-S only)\n"
 "	-S N    use DiSEqC uncommitted switch position N (DVB-S only)\n"
+"	-r sat  move DiSEqC rotor to satellite location, e.g. '13.0E' or '1.0W'\n"
+"	-R N    move DiSEqC rotor to position number N\n"
 "	-i N	spectral inversion setting (0: off, 1: on, 2: auto [default])\n"
 "	-n	evaluate NIT messages for full network scan (slow!)\n"
 "	-5	multiply all filter timeouts by factor 5\n"
@@ -2431,7 +2539,7 @@ int main (int argc, char **argv)
 
 	/* start with default lnb type */
 	lnb_type = *lnb_enum(0);
-	while ((opt = getopt(argc, argv, "5cnpa:f:d:O:k:I:S:s:o:x:t:i:l:vquPA:U")) != -1) {
+	while ((opt = getopt(argc, argv, "5cnpa:f:d:O:k:I:S:s:r:R:o:x:t:i:l:vquPA:U")) != -1) {
 		switch (opt) 
 		{
 		case 'a':
@@ -2474,6 +2582,14 @@ int main (int argc, char **argv)
 
 		case 'S':
 			uncommitted_switch_pos = strtoul(optarg, NULL, 0);
+			break;
+
+		case 'r':
+			strncpy(rotor_pos_name,optarg,sizeof(rotor_pos_name)-1);
+			break;
+
+		case 'R':
+			rotor_pos = strtoul(optarg, NULL, 0);
 			break;
 
 		case 'O':
@@ -2567,6 +2683,16 @@ int main (int argc, char **argv)
 		fprintf (stderr, "uncommitted_switch position needs to be < 16!\n");
 		return -1;
 	}
+
+	read_rotor_conf("rotor.conf");
+	if (strlen(rotor_pos_name)>0){
+		rotor_pos=rotor_name2nn(rotor_pos_name);
+		if (rotor_pos == 0){
+			fprintf(stderr,"Rotor position '%s' not found. Check config.",rotor_pos_name);
+			return -1;
+		}
+	}
+
 	if (initial)
 		info("scanning %s\n", initial);
 
diff -r 40368fdba59a scan.h
--- a/scan.h
+++ b/scan.h
@@ -103,6 +103,12 @@ typedef struct transponder {
 	uint32_t *other_f;			/* DVB-T freqeuency-list descriptor */
 } transponder_t;
 
+typedef struct rotorslot {
+	unsigned int nn;
+	int orbital_pos;	// 192  degrees*10
+	unsigned int we_flag;	// 0=W, 1=E
+	char angle_we[8];	// '19.2E'
+} rotorslot_t;
 
 #endif
 
# rotor.conf
# diseqc_position_number orbital_position
1 13.0E
2 19.2E
3 16.0E
4 10.0E
5 7.0E
6 5.0E
7 3.0E
10 8.0W
11 18.0W
13 27.5W
16 23.5E
17 26.0E
19 28.2E
26 1.0W
27 7.0W
28 12.5W














_______________________________________________
linux-dvb mailing list
linux-dvb@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb

[Index of Archives]     [Linux Media]     [Video 4 Linux]     [Asterisk]     [Samba]     [Xorg]     [Xfree86]     [Linux USB]

  Powered by Linux