Get the Best IPTV Service
/* rc2k.c ** 1.20.91 ** (formerly sabust1.c ** 5.31.91 ** Revisions include support for the new SA_MISC_CMND, SA_AZ_CMND modified to and renamed SA_JOG_CMND, and more baud rate options.) This program has been designed to give the program developer a tool to use to exercise the rc 1000. The user can send commands to the positioner, see the actual bytes which are transmitted, and view the reply received back from the positioner. The RC 2000 uses the SA Bus protocol to communicate with a personal computer. The SA Bus protocol was developed by Scientific Atlanta for control of communications equipment. The protocol defines the physical, electrical, and logical operation of the interface. When execution begins, the user is prompted to specify the baud rate and the comm port. The operation of this program is pretty self explanatory. The user is presented with three windows, a menu window - where the user is prompted to enter commands to the rc 2000, a transmit window - which displays all bytes sent to the positioner in both hex and ascii, if possible, and a receive window - which displays all bytes received from the rc 2000 in a format identical to that of the transmit window. This program uses the C ASYNCH MANAGER library (version 2.0) of serial routines available from BLAISE COMPUTING INC., 2560 Ninth Street, Suite 316, Berkeley, CA. 94710, (415) 540-5441. This program was compiled with the BORLAND TURBO C compiler, version 2.00. The project file is rc2k.prj. */ #include #include #include #include #include #include /* Here are the global literals. */ #define MENU_TOP_ROW 2 /* the window starting and ending rows */ #define MENU_BOTTOM_ROW 9 #define XMIT_TOP_ROW 11 #define XMIT_BOTTOM_ROW 15 #define RCV_TOP_ROW 17 #define RCV_BOTTOM_ROW 25 /* The following literals define the SA bus command codes. */ #define SA_QUERY_ID_CMND 0x30 #define SA_QUERY_CMND 0x31 #define SA_QUERY_NAME_CMND 0x35 #define SA_AUTO_CMND 0x32 #define SA_JOG_CMND 0x33 #define SA_POL_CMND 0x34 #define SA_MISC_CMND 0x36 #define STX 0x2 #define ETX 0x3 #define SAT_NAME_LNGTH 10 /* Here are the global variables. */ int com_port, baud_rate; /* These 2 variables hold the selected comm port (1 or 2), and the baud rate. */ struct text_info xmit_window_info, rcv_window_info; /* These two structures are used to hold the current status of the receive and transmit windows. This allows those windows to be restored when there is data to be written to those windows. */ int rcv_etx_cnt, rcv_etx_found = 0; /* These variables implement a system which generates a newline in the receive window after an ETX character is received. The idea is to generate a newline when the second character after the ETX is received. When an ETX character is received, 'found is set to one and 'cnt is reset to zero. As succeeding characters are received, 'found is still 1 and 'cnt is incremented. When 'cnt equals 2 a newline performed and 'found is reset to 0. */ /* The following routine restores a window based on a text_info data structure. The text_info structure is returned by the gettextinfo function. */ void window_restore(struct text_info *window_info) { /* Restore the window. */ window( window_info -> winleft, window_info -> wintop, window_info -> winright, window_info -> winbottom); /* Restore the curser position. */ gotoxy( window_info -> curx, window_info -> cury); return; } /* end - window_restore */ /* The following routine swaps windows. The curr_window text_info structure will receive the current window status, and the new_window text_info structure holds the parameters of the new window which will be created. */ void window_swap_curr_new( struct text_info *curr_window, struct text_info *new_window ) { gettextinfo( curr_window ); window_restore( new_window ); return; } /* end - window_swap_curr_new */ /* The following routine checks to see if the cursor is on the last row of the currently active window. If the cursor is on the bottom line, a 1 is returned, otherwise 0 is returned. */ int window_cursor_on_bottom_row() { struct text_info win; gettextinfo( &win ); if( (win.wintop + wherey()) > win.winbottom) return 1; else return 0; } /* end - window_cursor_on_bottom_row */ /* The following routine scrolls the current window upward, and leaves the cursor on the bottom row in column 1. The top row scrolls off of the top of screen. */ void window_scroll_up() { struct text_info win; /* Get the current window parameters. */ gettextinfo(&win); /* Move the text up one line. */ movetext( 1, win.wintop+1, 80, win.winbottom, 1, win.wintop); /* Position the cursor on the bottom row of the window and clear that row. */ gotoxy(1, win.winbottom - win.wintop + 1); clreol(); return; } /* The following routine generates a newline in a turbo c window enviroment. If the cursor is not at the bottom row of the window, a printf("\n") is performed, otherwise a window_scroll_up is performed. */ void window_newline() { struct text_info win; /* Get the current window parameters. */ gettextinfo(&win); if (1 == window_cursor_on_bottom_row()) window_scroll_up(); else printf("\n"); return; } /* end - window_newline */ /* The following routine clears the screen from the current cursor position to the end of the current window. The cursor position is changed and then returned to the original position. */ void clreos() { struct text_info info; unsigned char row; /* Get the existing window parameters. */ gettextinfo( &info ); /* Clear to the end of the line that line which contains the cursor. */ clreol(); /* Move the cursor down the window, clearing each line along the way. */ for (row = info.wintop + info.cury; row <= info.winbottom ;row++) { gotoxy( 1, wherey() + 1); clreol(); } /* Restore the cursor. */ gotoxy( (int) info.curx, (int) info.cury ); return; } /* end - clreos */ /* This routine displays a rc 2000 command string. The data is displayed in a hexadecimal format along with the ascii representation (if applicable). The input parameters are a pointer to the text_info structure of the window that will display the characters, a pointer to the string to be displayed and the length of the string. On exit, the window which was active on entry is restored. */ void display_xmit_data( struct text_info *xmit_window, unsigned char *str, unsigned int lngth) { unsigned int u; struct text_info prev_window; window_swap_curr_new( &prev_window, xmit_window); /* Display the characters. */ for (u=0; u < lngth ;u++) { /* See if a new line is needed. */ if (((u == 0) && (wherex() != 1)) || (wherex() > 70)) window_newline(); if (0 != isprint( (int) str[u])) printf("%02x '%c' ", str[u], (char) str[u] ); else printf("%02x ... ", str[u] ); } /* Restore the previous window. */ window_swap_curr_new( xmit_window, &prev_window); return; } /* end - display_xmit_data */ /* The following routine is called to check for the presence of and display data received by the serial port. This routine assumes that the receive window is not active when it is called. */ void display_rcv_data() { char rcv_char; /* holds the received character */ int size; /* holds the number of characters remaining in the input queue */ unsigned int status; /* When a call is made to read a character from the input queue, bits in the status word can be set to indicate that some kind of an error has occurred. Here's the bits that can be set and their meanings.... 0x0001 - input lost - receive characters lost because the queue was not read quickly enough. 0x0002 - internal error - the serial port interrupt service routine has lost its way. 0x0010 - parity error 0x0020 - overrun error - the uart detected an overrun, a character was lost, something maybe disabling the uart interrupt for long periods. 0x0040 - framing error - the stop bits were not received as expected. 0x0080 - break - the line was held in the spacing condition for at least the amount of time required to send one character. */ int window_swapped = 0; /* This variable will be set to 1 when the receive window becomes current (in response to a valid character received). On exit, if this variable is set, the window which was active on entry must be restored. */ struct text_info prev_window; /* used to store the window which was active on entry */ int err_code; /* holds the return value of the functions that read the serial port. 0 means that characters were read without error and 10 means no data was available. */ /* Stay in this loop as long receive data (or status errors) are available. */ for (;;) { /* See if any characters are ready. */ err_code = rdch_a2( com_port, &rcv_char, &size, &status); /* Exit loop if there are no characters ready and no status errors have occurred. */ if ((err_code == 10) && (0 == (status & STATUS_ERR))) break; /* See if the window needs to be swapped. */ if (window_swapped == 0) { window_swap_curr_new( &prev_window, &rcv_window_info); window_swapped=1; } /* See if a status error has occurred. */ if (status & STATUS_ERR) { window_newline(); printf("Status Error: %04x "); } /* See if a character is ready. */ else if (err_code == 0) { /* See if a newline is needed because of the reception of a previous ETX. */ if (rcv_etx_found != 0) { rcv_etx_cnt++; if (rcv_etx_cnt == 2) { rcv_etx_found = 0; window_newline(); } } /* See if a newline is needed because the current line is full. */ if (wherex() > 70) window_newline(); /* Display the characters. */ if (0 != isprint( (int) rcv_char)) printf("%02x '%c' ", (unsigned char) rcv_char, rcv_char ); else printf("%02x ... ", (unsigned char) rcv_char ); /* See if an ETX was received. */ if (rcv_char == ETX) { rcv_etx_found = 1; rcv_etx_cnt = 0; } } } /* end - for */ /* If the window was swapped, restore the window which was active when this routine was called. */ if (window_swapped != 0) window_swap_curr_new( &rcv_window_info, &prev_window); return; } /* end - display_rcv_data */ /* The following routine prompts the user to enter an alphabetic value and displays receive data as it arrives in the receive window. The input parameters are a string to prompt the user with and a character that sets the limit for the 'greatest' alphabetic value which will be accepted. If the limit is 'G' then A thru G will be accepted. The return value is the character which was entered. Lower case letters are accepted, but are converted to upper case on return. */ char prompt_alpha_display_rcv( char *prompt_str, char limit) { char ch; printf("%s", prompt_str); for (;;) { /* See if a character has been hit. */ if (0 != kbhit()) { /* A character is ready, read the character. */ ch = (char) getch(); /* See if the character is alphabetic. */ if (0 != isalpha(ch)) { /* The character is alphabetic, if it is lower case convert it to upper case. */ if (0 != islower(ch)) ch = (char) toupper(ch); /* See if the character is within the limits specified. If so, display the character and return. */ if ((ch >= 'A') && (ch <= limit)) { printf( "%c\n", ch); return ch; } } } /* Call a routine to display any receive data. */ display_rcv_data(); } /* end - for */ } /* end - prompt_alpha_display_rcv */ /* The following routine prompts the user to enter an alphabetic value. The input parameters are a string to prompt the user with and a character that sets the limit for the 'greatest' alphabetic value which will be accepted. If the limit is 'G' then A thru G will be accepted. The return value is the character which was entered. Lower case letters are accepted, but are converted to upper case on return. */ char prompt_alpha( char *prompt_str, char limit) { char ch; printf("%s", prompt_str); for (;;) { /* See if a character has been hit. */ if (0 != kbhit()) { /* A character is ready, read the character. */ ch = (char) getch(); /* See if the character is alphabetic. */ if (0 != isalpha(ch)) { /* The character is alphabetic, if it is lower case convert it to upper case. */ if (0 != islower(ch)) ch = (char) toupper(ch); /* See if the character is within the limits specified. If so, display the character and return. */ if ((ch >= 'A') && (ch <= limit)) { printf( "%c\n", ch); return ch; } } } } /* end - for */ } /* end - prompt_alpha */ /* The following routine prompts the user for an unsigned integer. The input parameter is a string which will be used to prompt the user and the return value is the numeric value entered by the user. */ unsigned int prompt_uint( char *prompt_str) { unsigned int u; printf( "%s", prompt_str); scanf( "%u", &u); return u; } /* end - prompt_uint */ /* The following routine prompts the user for a character. The input parameter is the string which will prompt the user and the return value is the character entered by the user. If the user enters an alphabetic value convert it to upper case. */ char prompt_char( char *prompt_str) { char ch; printf( "%s", prompt_str); ch = (char) getche(); /* If an alphabetic character was entered, convert it to upper case. */ if (0 != isalpha( ch )) ch = (char) toupper( ch ); if (ch != '\n') printf("\n"); return ch; } /* end - char_prompt */ /* The following routine calculates an exclusive-or checksum over a character array. The checksum is calculated on a byte by byte basis. */ unsigned char calc_xor_checksum( char *str, unsigned int lngth) { unsigned char sum; unsigned int u; if (lngth == 0) sum = 0; else { sum = str[0]; for (u=1; u= 49) && (uint <= 111)) { address = uint; gotoxy( 39, 1); printf("%03u", address); } fflush(stdin); break; case 'D': /* Send the query_id command. */ format_query_id_cmnd( address, &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'E': /* Send the query command. */ format_query_cmnd( address, &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'F': /* Send the query_name command. */ format_query_name_cmnd( address, prompt_uint("Enter the sat_index: "), &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'G': /* Send the auto command. */ /* Prompt for the polarization code. */ switch (prompt_alpha_display_rcv( "Enter polarization code, A.H_pol B.V_pol C.None: ", 'C')) { case 'A': pol = 'H'; break; case 'B': pol = 'V'; break; case 'C': pol = ' '; break; } fflush(stdin); /* Prompt for the satellite name. */ printf("Enter the satellite name: "); gets( sat_name ); format_auto_cmnd( address, pol, sat_name, &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'H': /* Send the az jog east command. */ format_jog_cmnd( address, 'E', speed_code, duration, &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'I': /* Send the az jog west command. */ format_jog_cmnd( address, 'W', speed_code, duration, &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'J': /* Send the elev jog down command. */ format_jog_cmnd( address, 'D', speed_code, duration, &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'K': /* Send the elev jog up command. */ format_jog_cmnd( address, 'U', speed_code, duration, &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'L': /* Send the goto hpol command. */ format_pol_cmnd( address, 'H', &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'M': /* Send the goto vpol command. */ format_pol_cmnd( address, 'V', &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'N': /* Send the skew clockwise command. */ format_pol_cmnd( address, 'C', &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'O': /* Send the skew counter clockwise command. */ format_pol_cmnd( address, 'W', &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'P': /* Send reset az miscellaneous command. */ format_misc_cmnd( address, 'R', 'A', &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'Q': /* Send reset el miscellaneous command. */ format_misc_cmnd( address, 'R', 'E', &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'R': /* Send autopol enable miscellaneous command. */ format_misc_cmnd( address, 'P', 'N', &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'S': /* Send autopol disable miscellaneous command. */ format_misc_cmnd( address, 'P', 'F', &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; case 'T': /* Send the az/el stop command. */ format_jog_cmnd( address, 'X', speed_code, duration, &str[0], &lngth); display_xmit_data( &xmit_window_info, &str[0], lngth); /* Transmit the data. */ wrtst_a1( com_port, lngth, str, &cnt); break; } /* end - switch */ } /* end - for */ /* Close the comm port. */ close_a2( com_port ); /* Clear the screen. */ window(1,1,80,25); clrscr(); } /* end - main */  Flash Sale Popup