A short program to check the data format for IC-7410 Keyspeed control.
#define MYRIG "/dev/ttyUSB0" int fd = open(MYRIG, O_RDWR | O_NOCTTY); output[0] = 0xfe; /* IC-7410 preamble */ output[1] = 0xfe; /* IC-7410 preamble */ output[2] = 0x80; /* IC-7410 CI-V address */ output[3] = 0x00; /* my PC address (any) */ output[4] = 0x14; /* IC-7410 command for set params */ output[5] = 0x0c; /* IC-7410 sub-command for keyspeed inquiry */ output[6] = 0xfd; /* IC-7410 postamble */ outputcount = 7; /* command length */ writecount = write(fd, &output, outputcount);
This is the inquiry and its response with different settings of the keyspeed volume.
[FE] [FE] [80] [00] [14] [0C] [FD]
[FE] [FE] [00] [80] [14] [0C] [00] [01] [FD] <- volume at min. ( 6 wpm)
[FE] [FE] [00] [80] [14] [0C] [01] [28] [FD] <- volume at center
[FE] [FE] [00] [80] [14] [0C] [02] [54] [FD] <- volume at max. (48 wpm)
Set several predefined keyspeed through the function keys.
void send_keyspeed(int wpm) { /* IC-7410 key speed */ static char output_ks [9] = {0xfe, 0xfe, 0x80, 0x00, 0x14, 0x0c, 0x01, 0x28, /* from 0x00,0x00 to 0x02,0x55 */ 0xfd}; switch(wpm) { case 1 : output_ks[6] = 0x00; output_ks[7] = 0x64;break; case 2 : output_ks[6] = 0x00; output_ks[7] = 0x96;break; case 3 : output_ks[6] = 0x01; output_ks[7] = 0x28;break; case 4 : output_ks[6] = 0x01; output_ks[7] = 0x92;break; } write(fd, output_ks, 9); }
By sending a series of dots at each speed, the element length is obtained by observing the waveform of the audio signal, and WPM is obtained by using the equation: WPM=1200/element_length [mS].
The measured curve (in red) differs slightly from a liner interpolation (in green) by the two points suggested by the manual, (0: 6 wpm, 255: 48 wpm). In either case, the parameters for {20|25|30|35} wpm shall be around {83, 112, 141, 170}, respectively.
So, in conclusion, a new version of the source code for CW Keybord is:
/* file name = ic7410m.c */ /* % gcc ic7410m.c -o ic7410m -lncurses */ #include <ncurses.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <termios.h> #include <string.h> #include <fcntl.h> #define BUFSIZE 4096 #define BAUDRATE B19200 #define MYRIG "/dev/ttyUSB0" int fd=-1; void send_cw(char* text); void send_keyspeed(int wpm) { /* IC-7410 key speed */ static char output_ks [9] = {0xfe, 0xfe, 0x80, 0x00, 0x14, 0x0c, 0x01, 0x28, /* from 0x00,0x00 to 0x02,0x55 */ 0xfd}; switch(wpm) { /* 20, 25, 30, 35 wpm */ case 1 : output_ks[6] = 0x00; output_ks[7] = 0x83;break; case 2 : output_ks[6] = 0x01; output_ks[7] = 0x12;break; case 3 : output_ks[6] = 0x01; output_ks[7] = 0x41;break; case 4 : output_ks[6] = 0x01; output_ks[7] = 0x70;break; } write(fd, output_ks, 9); } void send_cw(char* text) { /* IC-7410 send CW */ static char output [BUFSIZE] = {0xfe, 0xfe, 0x80, 0x00, 0x17}; char *p; int count; count=0; p=output+5; while(*p++ = *text++) { count++; if(count == 30) { /* IC-7410 max CW text length */ *p = 0xfd; /* IC-7410 postamble */ write(fd, output, 5+count+1); count=0; p=output+5; } } if(count) { *(--p) = 0xfd; /* replace zero with postamble */ write(fd, output, 5+count+1); } } void send_stored_text(int id) { /* use Function Keys */ static char *text_array[]={ "cq cq cq de jh1ood jh1ood jh1ood k ", /* F1 */ "qrz? de jh1ood k ", /* F2 */ "ur 5nn ^bk ", /* F3 */ "73 tu e e "}; /* F4 */ send_cw(text_array[id-1]); /* id=1, 2, ... */ attron(COLOR_PAIR(2)); printw (text_array[id-1]); attroff(COLOR_PAIR(2)); } void serial_init(void) { struct termios tio; memset(&tio, 0, sizeof(tio)); tio.c_cflag = CS8 | CLOCAL | CREAD; tio.c_cc[VTIME] = 0; tio.c_cc[VEOL ] = 0xfd; /* IC-7410 postamble */ tio.c_lflag = ICANON; tio.c_iflag = IGNPAR | ICRNL; cfsetispeed(&tio, BAUDRATE); cfsetospeed(&tio, BAUDRATE); tcsetattr (fd, TCSANOW, &tio); } int main (void) { int c, i, count=0, nrow, ncol, row=0, col=0; char word[BUFSIZE]; struct termios oldtio; fd = open(MYRIG, O_RDWR | O_NOCTTY); if (fd < 0) { fprintf(stderr,"Error: can not open %s n", MYRIG); return (-1); } tcgetattr (fd, &oldtio); serial_init(); initscr (); /* ncurses init */ raw (); noecho (); keypad (stdscr, TRUE); scrollok (stdscr, TRUE); getmaxyx (stdscr,nrow,ncol); start_color(); init_pair (1, COLOR_RED , COLOR_BLACK); init_pair (2, COLOR_YELLOW, COLOR_BLACK); attron (COLOR_PAIR(1)); printw("CW keyboard.."); attroff(COLOR_PAIR(1)); row=2; col=0; move(row, col); refresh (); while ( (c=getch()) != 0x04) { /* EOT */ switch (c) { case KEY_F(1): send_stored_text(1); break; case KEY_F(2): send_stored_text(2); break; case KEY_F(3): send_stored_text(3); break; case KEY_F(4): send_stored_text(4); break; case KEY_F(5): send_keyspeed (1); break; case KEY_F(6): send_keyspeed (2); break; case KEY_F(7): send_keyspeed (3); break; case KEY_F(8): send_keyspeed (4); break; case KEY_BACKSPACE: if(count) { /* only within a word */ getyx (stdscr, row, col); count--; col--; /* only within the same line */ mvaddch(row, col, ' '); move (row, col); /* cursor goes back */ } break; default: if(isprint(c)) { addch(c); word[count++] = c; } break; } getyx(stdscr, row, col); if(c == 0x0a || c==' ' && col >= ncol-10 || col == ncol) printw("n"); refresh(); if(c == 0x0a || c == ' ' || c == '.' || c == ',') { word[count] = 0; count=0; send_cw(word); } } tcsetattr(fd, TCSANOW, &oldtio); /* reset serial terminal */ endwin (); /* reset ncurses */ return EXIT_SUCCESS; }