/* * Copyright (C) 2012 William Robison * All right Reserved * Prior express permission is required for the * use of this software. */ #include #include #include #include #include #include #include #include #include #include "scrad.h" #include "scsim_align.h" #ifdef FTDI_LIBMPSSE #include "scsim_lib.h" #endif static int MIN = 60; static char Version[] = {"V1.0 " #ifdef FTDI_LIBMPSSE "libmpsse" #else "/dev/ttyUSB*" #endif }; static int signal_flag = 0; /* * CW mwssage table, the "********" is where the callsign * from the command line appears. */ static char id_string[][64] = { //0 1 2 3 ***4 //012345678901234567890123456789012345678901234567890123456789123 "CODE,******** ", "CODE,JUNO/WAVES DE ******** ", "CODE,HI JUNO PROGRAM DE ******** ", "CODE,HI JUNO GOODBYE DE ******** ", "" }; #define HI_DIT 1 #define HI_SPACE 0 #define HI_ID_END 2 #define HI_ID_BEG 3 static int hi_mode = 0; /* * This is the mesage thge goes out... HI_ID_BEG imnplies that the * key id left on after the ID message goes out... */ static int hi_juno[8][10] = { {HI_ID_BEG, HI_DIT, HI_DIT, HI_DIT, HI_SPACE, HI_DIT, HI_DIT, HI_SPACE, HI_SPACE, HI_SPACE}, {HI_DIT, HI_DIT, HI_DIT, HI_DIT, HI_SPACE, HI_DIT, HI_DIT, HI_SPACE, HI_SPACE, HI_ID_END}, {HI_DIT, HI_DIT, HI_DIT, HI_DIT, HI_SPACE, HI_DIT, HI_DIT, HI_SPACE, HI_SPACE, HI_ID_END}, {HI_DIT, HI_DIT, HI_DIT, HI_DIT, HI_SPACE, HI_DIT, HI_DIT, HI_SPACE, HI_SPACE, HI_ID_END}, {HI_DIT, HI_DIT, HI_DIT, HI_DIT, HI_SPACE, HI_DIT, HI_DIT, HI_SPACE, HI_SPACE, HI_ID_END}, {HI_DIT, HI_DIT, HI_DIT, HI_DIT, HI_SPACE, HI_DIT, HI_DIT, HI_SPACE, HI_SPACE, HI_ID_END}, {HI_DIT, HI_DIT, HI_DIT, HI_DIT, HI_SPACE, HI_DIT, HI_DIT, HI_SPACE, HI_SPACE, HI_ID_END}, {HI_DIT, HI_DIT, HI_DIT, HI_DIT, HI_SPACE, HI_DIT, HI_DIT, HI_SPACE, HI_SPACE, HI_ID_END}, }; #ifdef FTDI_LIBMPSSE struct SCSIM_PORT scsim_PORT; struct ftdi_context ftdic; int interface_ = INTERFACE_C; #else int ttyusb_fd = 0; char ttyusb_filename[32] = {""}; #endif /* * millisecond delay */ int delay_(int msec) { fd_set rdfs; struct timeval timeout; int retval = 0; if(msec) { FD_SET(0, &rdfs); timeout.tv_sec = 0; timeout.tv_usec = msec * 1000; retval = select(1, &rdfs, NULL, NULL, &timeout); } return retval; } /* * This illustrated the interface to function mapping * iplemented in the radio interface */ char *interface_text(int interface) { static char text[8][32]; static int text_index = 0; text_index++; text_index&=0x07; text[text_index][0] = 0; if(interface==INTERFACE_A) strcat(text[text_index], "CI-V"); if(interface==INTERFACE_B) strcat(text[text_index], "SPI"); if(interface==INTERFACE_C) strcat(text[text_index], "LCD"); if(interface==INTERFACE_D) strcat(text[text_index], "RS232"); return text[text_index]; } /* * Format time to the way we like to see it... * 2013-10-09T18:00:00 */ char *cztime(const time_t *ut) { static char buf[8][32]; static int idx = -1; struct tm *tm_ut; idx++; idx&= 0x07; memset(buf[idx], 0, 32); tm_ut = gmtime(ut); sprintf(buf[idx], "%4d-%02d-%02dT%02d:%02d:%02dZ", tm_ut->tm_year+1900, tm_ut->tm_mon+1, tm_ut->tm_mday, tm_ut->tm_hour, tm_ut->tm_min, tm_ut->tm_sec); return buf[idx]; } /* * Our help file, of course */ void help(FILE *out, char *argv) { fprintf(out, "%s %s\n", argv, Version); fprintf(out, " \n"); fprintf(out, " This is the HI JUNO timing control program for use with\n"); fprintf(out, " the KC0JFQ/ICARC radio control interface. The interface\n"); fprintf(out, " provides keying for the radio and code generation.\n"); fprintf(out, " \n"); fprintf(out, " The host program assumes that the system is syncheonized\n"); fprintf(out, " to UT using NTP and provides the timing for the \"HI\" message. \n"); fprintf(out, " The interface provides the code generation at 25WPM for station\n"); fprintf(out, " identification. \n"); fprintf(out, " \n"); fprintf(out, " -c \n"); fprintf(out, " You MUST supply your callsign (failing to \n"); fprintf(out, " provide your callsign will simply display )\n"); fprintf(out, " the help text and immediately exit)\n"); fprintf(out, " \n"); fprintf(out, " -p <*>\n"); #ifdef FTDI_LIBMPSSE fprintf(out, " Port Discovery is automatic when using \n"); fprintf(out, " LIBMPSSE. The radio interface ID and serial number\n"); fprintf(out, " are searched out to select the appropriate port (so\n"); fprintf(out, " there is no need to specify a serial port) \n"); fprintf(out, " Using this flag causes an error message to be \n"); fprintf(out, " displayed and the program immediately exits.\n"); #else fprintf(out, " *=USBn USB command port\n"); fprintf(out, " *=/dev/... TTY command port\n"); fprintf(out, " * others write to file\n"); #endif fprintf(out, " \n"); fprintf(out, " -m \n"); fprintf(out, " defaults to %d second 'chip' rate, \n", MIN); fprintf(out, " that is the time of a dit and the following space \n"); fprintf(out, " so for HI JUNO we want to see a value of 60 in this \n"); fprintf(out, " field to generate the 30 second key-down period. \n"); fprintf(out, " Shorter or longer times may be specified for testing.\n"); fprintf(out, " -I\n"); fprintf(out, " Alternate ID mode \n"); fprintf(out, " The default ID mode is that suggested on the\n"); fprintf(out, " JPL web page, that is to send callsign (in this \n"); fprintf(out, " implementation at 25WPM) during the first \"dit\" \n"); fprintf(out, " The alternate method, originally implemented\n"); fprintf(out, " in this software, was to ID during the last minute of \n"); fprintf(out, " the 10 minute cycle. This method is NOT preferred\n"); fprintf(out, " as it sends carrier during the inter-word quiet time.\n"); fprintf(out, " \n"); return; } /* * */ void signal_handler_action(int signal) { signal_flag = signal | 0x80000000; } /* * */ int txt_control(char *out_strg, time_t ut, int now86400, int flag) { #ifdef FTDI_LIBMPSSE int sts; static char in_strg[1024] = {1024*0}; #else static char cbuf[1024]; #endif static char old_strg[1024] = {1024*0}; int len; int now600, now60, cell; now60 = now86400%MIN; // 1 minute cycle now600 = now86400%(MIN*10); // 10 minute cycle cell = now600/MIN; // chip cell if(flag) memset(old_strg, 0, 1024); len = strlen(out_strg); // include CR character if(len) { #ifdef FTDI_LIBMPSSE sts = scsim_write(&scsim_PORT, (unsigned char*)out_strg, len, stdout); len--; // eliminate CR character out_strg[len] = 0; // from out_strg memset(in_strg, 0, 256); sts = scsim_read(&scsim_PORT, (unsigned char*)in_strg, 255, stdout); #else cbuf[0] = 0; if(strncmp(ttyusb_filename, "/dev", 4)) { sprintf(&cbuf[strlen(cbuf)], "%4d", now600); sprintf(&cbuf[strlen(cbuf)], " %3d", now60); sprintf(&cbuf[strlen(cbuf)], " %2d", cell); if(now60<(MIN/2)) sprintf(&cbuf[strlen(cbuf)], " cell"); else sprintf(&cbuf[strlen(cbuf)], " gap "); sprintf(&cbuf[strlen(cbuf)], " \""); len--; // eliminate CR character out_strg[len] = 0; // from out_strg } sprintf(&cbuf[strlen(cbuf)], "%s", out_strg); if(strncmp(ttyusb_filename, "/dev", 4)) sprintf(&cbuf[strlen(cbuf)], "\\r\"\n"); write(ttyusb_fd, cbuf, strlen(cbuf)); #endif #ifdef FTDI_LIBMPSSE #endif if(len<18) { strcat(out_strg, " "); out_strg[18] = 0; } if(strcmp(old_strg, out_strg)) { fprintf(stdout, "%10d %3d %3d %3d", now86400, now600, now60, cell); fprintf(stdout, " %4d Command(%2d) ", __LINE__, len); fprintf(stdout, "\"%s\"", out_strg); fprintf(stdout, " %s\n", cztime(&ut)); fflush(stdout); strcpy(old_strg, out_strg); } } #ifdef FTDI_LIBMPSSE scsim_LEDs(&scsim_PORT, stdout, now86400&2, now86400&1); #endif return len; } /* * Generte command to interface * override: 0 Key command based on time * top of the 10 minute cycle, send CW ID * top of minute send ON * botom of minute send OFF * 1 Force Key OFF * 2 Done, so send CW ID * */ int key_control(int override) { static char out_strg[1024] = {1024*0}; int len; int delay_value; int now86400, now600, now60; time_t ut; int cell; int flag = 0; now86400 = scsim_align(1, 0, 86400, NULL, __LINE__) % 86400; ut = time(0); now60 = now86400%MIN; // 1 minute cycle now600 = now86400%(MIN*10); // 10 minute cycle cell = now600/MIN; // chip cell sprintf(out_strg, "KEYN\r"); switch(override) { case 1: sprintf(out_strg, "KEYN\r"); flag = 1; break; case 2: sprintf(out_strg, "%s\r", id_string[3]); flag = 1; break; case 0: if(now60<(MIN/2)) switch(hi_juno[hi_mode][cell]) { case HI_SPACE: sprintf(out_strg, "KEYN\r"); break; case HI_DIT: sprintf(out_strg, "KEYN,KEY0,KEY1\r"); break; case HI_ID_BEG: if(now60==0) { sprintf(out_strg, "%s\r", id_string[0]); break; } if (now60<8) { sprintf(out_strg, "PING\r"); break; } sprintf(out_strg, "KEYN,KEY0,KEY1\r"); break; case HI_ID_END: if(MIN>7) sprintf(out_strg, "%s\r", id_string[1]); else sprintf(out_strg, "%s\r", id_string[0]); break; } } len=txt_control(out_strg, ut, now86400, flag); delay_value = 750; if(!strncmp(out_strg, "CODE,", 5)) delay_value = (len-2)*525 + 500; return delay_value; } /* * */ int main(int argc, char **argv) { /* 0123456789ABCDEF */ int len; char out_strg[1024] = {1024*0}; // char old_strg[1024] = {1024*0}; // char in_strg[1024] = {1024*0}; char callsign[32] = {""}; char *cs; char opt; int delay_value; #ifdef FTDI_LIBMPSSE int sts; #endif int time_flg = 1; int i=0; int now86400; time_t ut; struct sigaction new_action, old_action; /******************** * command line arguments ********************/ fprintf(stdout, "%s %s\n", argv[0], Version); while ((opt = getopt(argc, argv, "?hc:m:p:I")) != -1) { switch(opt) { default: case 'h': case '?': help(stdout, argv[0]); exit(0); case 'I': hi_mode++; hi_mode &= 7; break; case 'p': #ifdef FTDI_LIBMPSSE fprintf(stdout, "port discovery is automatic when using MPSSE \n"); exit(0); #else if(!strncmp(optarg, "USB", 3)) { strcpy(ttyusb_filename, "/dev/tty"); strcat(ttyusb_filename, optarg); fprintf(stdout, " TTY Port: %s\n", ttyusb_filename); } else if(!strncmp(optarg, "/dev", 4)) { strcpy(ttyusb_filename, optarg); fprintf(stdout, " TTY Port: %s\n", ttyusb_filename); } else { strcpy(ttyusb_filename, optarg); fprintf(stdout, " TTY File: %s\n", ttyusb_filename); } #endif break; case 'c': strcpy(callsign, optarg); break; case 'm': MIN = strtol(optarg, NULL, 10); if (MIN<2) MIN = 2; break; } } if(!strlen(callsign)) { help(stdout, argv[0]); exit(0); } i = 0; while(strlen(id_string[i])) { cs=strstr(id_string[i], "********"); strcpy(cs, callsign); i++; } /******************** * Setup control-C signal ********************/ new_action.sa_handler = signal_handler_action; sigemptyset (&new_action.sa_mask); new_action.sa_flags = 0; sigaction (SIGINT, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (SIGINT, &new_action, NULL); sigaction (SIGHUP, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (SIGHUP, &new_action, NULL); sigaction (SIGTERM, NULL, &old_action); if (old_action.sa_handler != SIG_IGN) sigaction (SIGTERM, &new_action, NULL); /******************** * Signon on message... * so we know how we are to access the device ********************/ fprintf(stdout, "%s HI JUNO de %s\n", argv[0], callsign); #ifdef FTDI_LIBMPSSE fprintf(stdout, " (does not depend on ftdi_sio.ko)\n"); #else fprintf(stdout, " (needs kernel newer than 2.6.32 for ftdi_sio.ko)\n"); #endif if(0) { i = 0; while(strlen(id_string[i])) fprintf(stdout, " %s\n", id_string[i++]); fprintf(stdout, " \n"); } /******************** * scan for our device ********************/ #ifdef FTDI_LIBMPSSE if((sts=scsim_init(&ftdic, NULL, stdout)) < 0) { fprintf(stderr, "\"%s\" %d=scsim_init();\n", ftdi_get_error_string(&ftdic), sts); exit(EXIT_FAILURE); } #else ttyusb_fd = open(ttyusb_filename, O_RDWR); fprintf(stdout, "%d=fopen(%s, O_RDWR);\n", ttyusb_fd, ttyusb_filename); if(!ttyusb_fd) exit(EXIT_FAILURE); #endif fprintf(stdout, "\n"); /******************** * open our device ********************/ #ifdef FTDI_LIBMPSSE scsim_open(&scsim_PORT, interface_, stdout, 0); delay_(100); fprintf(stdout, "LEDs off\n"); scsim_LEDs(&scsim_PORT, stdout, 0, 0); delay_(1000); #endif fprintf(stdout, " now86400 " "now600 " "now60 " "cell " "LINE " "Radio I/F Command\n"); fflush(stdout); if(1) { now86400 = scsim_align(1, 0, 86400, NULL, __LINE__) % 86400; ut = time(0); #ifdef FTDI_LIBMPSSE scsim_LEDs(&scsim_PORT, stdout, 0, 1); #endif sprintf(out_strg, "ECHO,0\r"); len=txt_control(out_strg, ut, now86400, 0); delay_(900); } if(time_flg) { ut = time(0); now86400 = scsim_align(1, 0, 86400, NULL, __LINE__) % 86400; sprintf(out_strg, "TIME,%08X\r", now86400 % 86400); len=txt_control(out_strg, ut, now86400, 0); delay_(900); } if(1) { now86400 = scsim_align(1, 0, 86400, NULL, __LINE__) % 86400; ut = time(0); sprintf(out_strg, "CWPM,25\r"); len=txt_control(out_strg, ut, now86400, 0); delay_(900); } if(1) { now86400 = scsim_align(1, 0, 86400, NULL, __LINE__) % 86400; ut = time(0); #ifdef FTDI_LIBMPSSE scsim_LEDs(&scsim_PORT, stdout, 1, 1); #endif sprintf(out_strg, "%s\r", id_string[2]); len=txt_control(out_strg, ut, now86400, 0); delay_value = (len-1)*525; delay_(delay_value); } #ifdef FTDI_LIBMPSSE scsim_LEDs(&scsim_PORT, stdout, 0, 0); #endif while(!signal_flag) { delay_value = key_control(0); delay_(delay_value); i++; } fprintf(stdout, "Send last ID string\n"); delay_(delay_value); delay_value = key_control(1); delay_(delay_value); delay_value = key_control(2); delay_(delay_value); #ifdef FTDI_LIBMPSSE scsim_close(&scsim_PORT, stdout); #else if(strncmp(ttyusb_filename, "/dev", 4)) { close(ttyusb_fd); } #endif fprintf(stdout, "CLOSE\n"); exit(0); }