IC-7410 Keyspeed

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].

keyspeed

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;
}

Leave a comment