void SpectrumView::draw ( void ) { //Clear Widget Fl_Box::draw(); int W = w() - padding_right; int H = h() - padding_bottom; if ( !_bands ) { analyze_data( W ); } //Draw grid fl_color(fl_color_add_alpha(fl_rgb_color( 100,100,100), 50 )); draw_semilog(); fl_push_clip( x(),y(),W,H); fl_color(fl_color_add_alpha( selection_color(), 20 )); fl_push_matrix(); fl_translate( x(), y() + 2 ); fl_scale( W,H- 2 ); fl_begin_polygon(); fl_vertex(0.0,1.0); draw_curve(); fl_vertex(1.0,1.0); fl_end_polygon(); fl_color(fl_color_add_alpha( selection_color(), 100 )); fl_begin_line(); fl_line_style(FL_SOLID,2); /* fl_vertex(0.0,1.0); */ draw_curve(); /* fl_vertex(1.0,1.0); */ fl_end_line(); fl_pop_matrix(); fl_line_style(FL_SOLID,0); fl_pop_clip(); }
// Try to identify format of drives with headers in cylinder head sector // format (CHS). // Head will be left at specified cylinder on return // // drive_params: Drive parameters determined so far and return what we have determined // deltas: MFM delta time transition data to analyze (filled after read) // max_delta: Size of deltas array // cyl: cylinder to test // head: head to test int analyze_chs(DRIVE_PARAMS *drive_params, void *deltas, int max_deltas, int cyl, int head) { int rc; rc = analyze_header(drive_params, cyl, head, deltas, max_deltas); if (rc != 2) { // Corvus H doesn't have separate data area if (drive_params->controller != CONTROLLER_CORVUS_H) { rc |= analyze_data(drive_params, cyl, head, deltas, max_deltas); } } // If we either got no valid information or multiple possible values try // cyl 1 head 1. Cyl 0 head 0 is poor for distinguishing different header // formats. Also may help if first track has too many read errors. // Analyzing track 0 is useful for detecting the weird multiple formats for // the DEC RQDX3 so it is tested first. if (rc != 0) { msg(MSG_INFO,"Retrying on a different cylinder and head\n"); cyl = cyl + 1; head = 1; if (analyze_header(drive_params, cyl, head, deltas, max_deltas) == 2) { return 1; } if (analyze_data(drive_params, cyl, head, deltas, max_deltas) == 2) { // IS THIS NEEDED? if (drive_params->controller == CONTROLLER_WD_1006) { drive_params->controller = CONTROLLER_RUSSIAN; } if (analyze_data(drive_params, cyl, head, deltas, max_deltas) == 2) { drive_params->controller = CONTROLLER_WD_1006; return 1; } msg(MSG_FORMAT,"Changed controller type to %s\n", mfm_controller_info[drive_params->controller].name); } } analyze_sectors(drive_params, cyl, deltas, max_deltas); return 0; }
// Try to identify format of drives with headers in logical block address // format (LBA). // Head will be left at specified cylinder on return // // drive_params: Drive parameters determined so far and return what we have determined // deltas: MFM delta time transition data to analyze (filled after read) // max_delta: Size of deltas array // cyl: cylinder to test // head: head to test int analyze_lba(DRIVE_PARAMS *drive_params, void *deltas, int max_deltas, int cyl, int head) { int rc = 0; // Loop variables int poly, init, cont; int nsec_ndx; int i; // The best match CRC and controller type info so far CRC_INFO header_crc_info; int controller_type = -1; // Numbers of good sectors found int good_header_count, previous_good_header_count = 0; // Variable to restore global error print mask int msg_mask_hold; // The status of each sector decoded. SECTOR_STATUS sector_status_list[MAX_SECTORS]; // And read status SECTOR_DECODE_STATUS status; int best_heads = 0; int best_sectors = 0; #if 0 decode_errors = ~1; msg_set_err_mask(decode_errors); #endif header_crc_info.poly = 0; drive_params->num_sectors = MAX_SECTORS; drive_params->num_head = MAX_HEAD; // Don't use ECC while trying to find format drive_params->header_crc.ecc_max_span = 0; drive_params->data_crc.ecc_max_span = 0; drive_params->first_sector_number = 0; drive_read_track(drive_params, cyl, head, deltas, max_deltas); // Try an exhaustive search of all the formats we know about. If we get too // many we may have to try something smarter. for (cont = 0; mfm_controller_info[cont].name != NULL; cont++) { if (mfm_controller_info[cont].analyze_type != CINFO_LBA) { continue; // **** } // Make sure these get set at bottom for final controller picked // Sector size will be set when we analyze the data header drive_params->controller = cont; drive_params->sector_size = mfm_controller_info[cont].analyze_sector_size; for (poly = mfm_controller_info[cont].header_start_poly; poly < mfm_controller_info[cont].header_end_poly; poly++) { drive_params->header_crc.poly = mfm_all_poly[poly].poly; drive_params->header_crc.length = mfm_all_poly[poly].length; for (init = mfm_controller_info[cont].start_init; init < mfm_controller_info[cont].end_init; init++) { // If not correct size don't try this initial value if (!(mfm_all_init[init].length == -1 || mfm_all_init[init].length == drive_params->data_crc.length)) { continue; } for (drive_params->num_head = 2; drive_params->num_head < 16; drive_params->num_head++) { for (nsec_ndx = 0; mfm_lba_num_sectors[nsec_ndx] != -1; nsec_ndx++) { drive_params->num_sectors = mfm_lba_num_sectors[nsec_ndx]; msg(MSG_DEBUG, "Trying controller %s heads %d sectors %d\n", mfm_controller_info[drive_params->controller].name, drive_params->num_head, drive_params->num_sectors); print_crc_info(&drive_params->header_crc, MSG_DEBUG); drive_params->header_crc.init_value = trim_value(mfm_all_init[init].value, drive_params->header_crc.length); drive_params->data_crc = drive_params->header_crc; mfm_init_sector_status_list(sector_status_list, drive_params->num_sectors); msg_mask_hold = msg_set_err_mask(decode_errors); // Decode track status = mfm_decode_track(drive_params, cyl, head, deltas, NULL, sector_status_list); msg_set_err_mask(msg_mask_hold); if (status & SECT_ZERO_HEADER_CRC) { msg(MSG_DEBUG, "Found zero CRC header controller %s:\n", mfm_controller_info[drive_params->controller].name); print_crc_info(&drive_params->header_crc, MSG_DEBUG); } // Now find out how many good sectors we got with these parameters good_header_count = 0; for (i = 0; i < drive_params->num_sectors; i++) { if (!(sector_status_list[i].status & SECT_BAD_HEADER)) { good_header_count++; } } // If we found at least 2 sectors if (good_header_count >= 2) { // If we have a previous match print both if (header_crc_info.poly != 0) { msg(MSG_ERR_SERIOUS, "Found multiple matching header parameters. Will use largest matches:\n"); msg(MSG_ERR_SERIOUS, "Matches %d controller %s ", good_header_count, mfm_controller_info[drive_params->controller].name); print_crc_info(&drive_params->header_crc, MSG_ERR_SERIOUS); msg(MSG_ERR_SERIOUS, "Matches %d controller %s ", previous_good_header_count, mfm_controller_info[controller_type].name); print_crc_info(&header_crc_info, MSG_ERR_SERIOUS); rc = 1; } // And keep the best if (good_header_count > previous_good_header_count) { best_heads = drive_params->num_head; best_sectors = drive_params->num_sectors; header_crc_info = drive_params->header_crc; header_crc_info.ecc_max_span = mfm_all_poly[poly].ecc_span; controller_type = drive_params->controller; previous_good_header_count = good_header_count; } } } } } } } // Set for final controller we picked. We should be able to identify // the header format without start_time_ns properly set. We // Won't get all the sectors until we do so we set it here. drive_params->start_time_ns = mfm_controller_info[controller_type].start_time_ns; drive_params->sector_size = mfm_controller_info[controller_type].analyze_sector_size; drive_params->num_head = best_heads; drive_params->num_sectors = best_sectors; // Print what we found and put it in drive_params if (header_crc_info.poly != 0) { msg(MSG_INFO, "Header CRC Information:\n"); print_crc_info(&header_crc_info, MSG_INFO); msg(MSG_INFO, "Controller type %s\n", mfm_controller_info[controller_type].name); msg(MSG_INFO, "Number of sectors %d number of heads %d\n", drive_params->num_sectors, drive_params->num_head); } else { // This is fatal since if we can't continue to next analysis msg(MSG_FATAL, "Unable to determine CRC & Controller type\n"); rc = 2; } drive_params->header_crc = header_crc_info; drive_params->controller = controller_type; if (rc != 2) { rc = analyze_data(drive_params, cyl, head, deltas, max_deltas); } return rc; }
int main(int argc, char **argv) { uint8_t w_data[FIFO_SIZE]; uint8_t r_data[FIFO_SIZE]; uint8_t t_data[FIFO_SIZE]; struct timeval tm1, tm2; unsigned long elapsed_time; int buffersize, opt, length, s, destination_port, ret; struct ifaddrs *ifap, *ifa; struct sockaddr_in *bsa; const int on = 1; struct ftdi2s88_t fs88; bzero(bus0_actual, sizeof(bus0_actual)); bzero(bus1_actual, sizeof(bus1_actual)); bzero(bus0_state, sizeof(bus0_state)); bzero(bus1_state, sizeof(bus1_state)); memset(bus0_ct0, 0xff, sizeof(bus0_ct0)); memset(bus0_ct1, 0xff, sizeof(bus0_ct1)); memset(bus1_ct0, 0xff, sizeof(bus1_ct0)); memset(bus1_ct1, 0xff, sizeof(bus1_ct1)); char *udp_dst_address = (char *)malloc(16); if (!udp_dst_address) { fprintf(stderr, "can't alloc udp_dst_address memory\n"); exit(1); } char *bcast_interface = (char *)malloc(16); if (!bcast_interface) { fprintf(stderr, "can't alloc bcast_interface memory\n"); exit(1); } strcpy(udp_dst_address, "255.255.255.255"); strcpy(bcast_interface, "br-lan"); destination_port = 15731; /* setting defaults */ fs88.inverting = 0; fs88.baudrate = BAUDRATE; length = S88_DEF_BITS; fs88.background = 0; fs88.hw_id = 0x5338; fs88.hash = 0x5338; while ((opt = getopt(argc, argv, "H:I:b:dr:l:h?")) != -1) { switch (opt) { case 'b': if (strlen(optarg) <= 15) { /* IP address begins with a number */ if ((optarg[0] >= '0') && (optarg[0] <= '9')) { strcpy(udp_dst_address, optarg); } else { bzero(bcast_interface, 16); strcpy(bcast_interface, optarg); } } else { fprintf(stderr, "UDP broadcast address or interface error: %s\n", optarg); exit(1); } break; case 'H': fs88.hash = atoi(optarg); break; case 'I': fs88.hw_id = atoi(optarg); break; case 'i': fs88.inverting = 1; break; case 'd': fs88.background = 1; break; case 'r': fs88.baudrate = atoi(optarg); break; case 'l': length = atoi(optarg); break; case 'h': case '?': print_usage(basename(argv[0])); exit(0); break; default: fprintf(stderr, "Unknown option %c\n", opt); print_usage(basename(argv[0])); exit(1); } } /* get the broadcast address */ getifaddrs(&ifap); for (ifa = ifap; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr) { if (ifa->ifa_addr->sa_family == AF_INET) { bsa = (struct sockaddr_in *)ifa->ifa_broadaddr; if (!strncmp(ifa->ifa_name, bcast_interface, strlen(bcast_interface))) udp_dst_address = inet_ntoa(bsa->sin_addr); } } } /* prepare udp socket struct */ bzero(&fs88.baddr, sizeof(fs88.baddr)); fs88.baddr.sin_family = AF_INET; fs88.baddr.sin_port = htons(destination_port); s = inet_pton(AF_INET, udp_dst_address, &fs88.baddr.sin_addr); if (s <= 0) { if (!s) { fprintf(stderr, "UDP IP address invalid\n"); } else { fprintf(stderr, "invalid address family\n"); } exit(1); } if (!fs88.background) { printf("using broadcast address %s\n", udp_dst_address); } /* prepare UDP sending socket */ fs88.sb = socket(AF_INET, SOCK_DGRAM, 0); if (fs88.sb < 0) { fprintf(stderr, "error creating UDP sending socket: %s\n", strerror(errno)); exit(1); } ret = setsockopt(fs88.sb, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); if (ret < 0) { fprintf(stderr, "error setup UDP broadcast option: %s\n", strerror(errno)); exit(1); } if (do_init(&fs88)) exit(-1); bzero(w_data, sizeof(w_data)); ret = fill_data(&fs88, w_data, sizeof(w_data), length); if (ret < 0) { fprintf(stderr, "to many data bits\n"); exit(1); } if (fs88.background) { pid_t pid; /* Fork off the parent process */ pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); } /* If we got a valid PID, then we can exit the parent process. */ if (pid > 0) { printf("Going into background ...\n"); exit(0); } } buffersize = sizeof(w_data); bzero(test_data, sizeof(test_data)); memset(&t_data[16 + 17 * 4], 0x88, 16); #if 0 /* testing: simple bit pattern */ memcpy(t_data, test_data, sizeof(test_data)); #endif // for (ti = 0; ti < 20; ti++) { for (;;) { gettimeofday(&tm1, NULL); ret = ftdi_write_data(fs88.ftdic, w_data, buffersize); if (ret < 0) { fprintf(stderr, "ftdi_write_data faild: %s", ftdi_get_error_string(fs88.ftdic)); break; } ret = ftdi_read_data(fs88.ftdic, r_data, buffersize); if (ret < 0) { fprintf(stderr, "ftdi_read_data faild: %s", ftdi_get_error_string(fs88.ftdic)); break; } #if 0 /* testing */ if (ti == 6) { manipulate_test_data(t_data, 5, 0x08); manipulate_test_data(t_data, 9, 0x88); } if (ti == 7) { manipulate_test_data(t_data, 8, 0x88); manipulate_test_data(t_data, 9, 0x80); } if (ti == 11) manipulate_test_data(t_data, 8, 0x00); memcpy(r_data, t_data, sizeof(r_data)); #endif if (analyze_data(&fs88, r_data, length)) break; gettimeofday(&tm2, NULL); elapsed_time = 1E6 * (tm2.tv_sec - tm1.tv_sec) + (tm2.tv_usec - tm1.tv_usec); if ((S88_INTERVAL - elapsed_time) > DEFAULT_TASK_T) usleep(S88_INTERVAL - elapsed_time); gettimeofday(&tm2, NULL); elapsed_time = 1E6 * (tm2.tv_sec - tm1.tv_sec) + (tm2.tv_usec - tm1.tv_usec); #if 0 if (!fs88.background) printf("send %d bytes in %ld usecs\n", FIFO_SIZE, elapsed_time); #endif } /* free(udp_dst_address); free(bcast_interface); */ exit(1); }