CW Keyboard (2)

cwkb1

Minor improvement to my old program adding menus for speed change and fixed messages.

cwkb2

The following is the source code.

/* file name = ic7410.c */
/* % gcc ic7410.c -o ic7410 -lncurses */
#include <ncurses.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#define  ENTER      10
#define  ESCAPE     27
#define  NROWMIN    30
#define  NCOLMIN    80
#define  BUFSIZE  1024
#define  BAUDRATE B19200
#define  MYRIG    "/dev/ttyUSB0"

static int speed[]={15,20,25,30,35,40,45,50};
static int nspeed =sizeof(speed) / sizeof(speed[0]);

static char *text_array[]={
  "cq cq cq de jh1ood jh1ood jh1ood k ", 
  "de jh1ood jh1ood jh1ood k ",
  "qrz? de jh1ood k ",
  "ur 5nn ^bk ",
  "73 tu e e "};
static int ntext =sizeof(text_array) / sizeof(text_array[0]);

int fd=-1;


void init_curses()
{
    initscr    ();
    start_color();
    noecho     ();
    raw        ();
    keypad     (stdscr, TRUE);
    scrollok   (stdscr, TRUE);
    curs_set   (0);
    init_pair  (1,COLOR_WHITE,COLOR_BLUE);
    init_pair  (2,COLOR_BLUE,COLOR_WHITE);
    init_pair  (3,COLOR_RED,COLOR_WHITE);
    init_pair  (4,COLOR_BLACK,COLOR_GREEN);
}

void draw_menubar(WINDOW *menubar)
{
    wbkgd(menubar,COLOR_PAIR(2));
    waddstr(menubar," WPM ");
    wattron(menubar,COLOR_PAIR(3));
    waddstr(menubar,"(F1)");
    wattroff(menubar,COLOR_PAIR(3));
    wmove(menubar,0,20);
    waddstr(menubar," Messages ");
    wattron(menubar,COLOR_PAIR(3));
    waddstr(menubar,"(F2)");
    wattroff(menubar,COLOR_PAIR(3));
}

WINDOW **draw_menu1(int start_col)
{
    int i;
    WINDOW **items;
    items=(WINDOW **)malloc((nspeed+1)*sizeof(WINDOW *));

    items[0]=newwin(nspeed+2,9,1,start_col);
    wbkgd(items[0],COLOR_PAIR(2));
    box(items[0],ACS_VLINE,ACS_HLINE);
    for (i=1;i<=nspeed;i++) {
    	items[i]=subwin(items[0],1,7,i+1,start_col+1);
        wprintw(items[i],"%2d WPM",speed[i-1]);
    }
    wbkgd(items[1],COLOR_PAIR(1));
    wrefresh(items[0]);
    return items;
}

WINDOW **draw_menu2(int start_col)
{

    int i;
    WINDOW **items;
    items=(WINDOW **)malloc((ntext+1)*sizeof(WINDOW *));

    items[0]=newwin(ntext+2,49,1,start_col);
    wbkgd(items[0],COLOR_PAIR(2));
    box(items[0],ACS_VLINE,ACS_HLINE);
    for (i=1;i<=ntext;i++) {
    	items[i]=subwin(items[0],1,47,i+1,start_col+1);
        wprintw(items[i],"%s",text_array[i-1]);
    }
    wbkgd(items[1],COLOR_PAIR(1));
    wrefresh(items[0]);
    return items;
}

void delete_menu(WINDOW **items,int count)
{
    int i;
    for (i=0;i<count;i++)
        delwin(items[i]);
    free(items);
}

int scroll_menu(WINDOW **items,int count)
{
    int key;
    int selected=0;
    while (1) {
        key=getch();
        if (key==KEY_DOWN || key==KEY_UP) {
            wbkgd(items[selected+1],COLOR_PAIR(2));
            wnoutrefresh(items[selected+1]);
            if (key==KEY_DOWN) {
                selected=(selected+1) % count;
            } else {
                selected=(selected+count-1) % count;
            }
            wbkgd(items[selected+1],COLOR_PAIR(1));
            wnoutrefresh(items[selected+1]);
            doupdate();
        } else if (key==ESCAPE) {
            return -1;
        } else if (key==ENTER) {
            return selected;
        }
    }
}

void send_cw(char* text);

/* IC-7410 key speed set */
/* the parameter 0-255 relates to 6wpm-48wpm */

void send_keyspeed(int wpm) {
  static char output_ks [9] =
   {0xfe, 0xfe, 0x80, 0x00, 0x14, 0x0c,
    0x01, 0x28, /* from 0x00,0x00 to 0x02,0x55 */
    0xfd};
  int param, p0, p1, p2;

  if(wpm <  6) wpm =  6;
  if(wpm > 48) wpm = 48;
  param = 255.0 * ((double)wpm - 6.0) / (48.0 - 6.0) + 0.0;
  p0 =  param      % 10;
  p1 = (param/ 10) % 10;
  p2 = (param/100) % 10;
  output_ks[6] = p2;
  output_ks[7] = 16*p1+p0;
/* because param=123 goes as 0x01, 0x23 (BCD) */
  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 */
  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, count=0, nrow, ncol, row=0, col=0;
  char   word[BUFSIZE];
  struct termios oldtio;
  int selected_item;
  WINDOW *menubar,*messagebar, **menu_items;

/* IC-7410 USB I/F initialize */
  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();

/* ncurses initialize */
  init_curses();
  getmaxyx   (stdscr,nrow,ncol);
  if(nrow<NROWMIN || ncol < NCOLMIN) {
     row=1; col=0; move(row, col);
     printw("Current Window size is %d rows, %d columns. \n\n"
            ,nrow, ncol);
     printw("Please make the Window size greater than %d rows, %d columns. \n"
            ,NROWMIN, NCOLMIN);
     printw("Hit anykey.. \n");
     getch();
     endwin();
     return EXIT_FAILURE;
  }
  bkgd(COLOR_PAIR(4));
  menubar   =subwin(stdscr,1,40,0, 0);
  messagebar=subwin(stdscr,1,10,0,ncol-10); /* 10chars */
  wattron(messagebar, COLOR_PAIR(2));
  draw_menubar(menubar);
  row=5; col=0; move(row, col);
  refresh();

  while ( (c=getch()) != 0x04) { /* ^d, EOT */
    switch (c) {
      case KEY_F(1):
            menu_items=draw_menu1(0);
            selected_item=scroll_menu(menu_items,nspeed);
            delete_menu(menu_items,nspeed);
            if (selected_item<0)
                ;
            else {
	        wclear(messagebar);
                wprintw(messagebar,
                  "Now %2d WPM",speed[selected_item]); /* 10chars */
		send_keyspeed(speed[selected_item]);
	    }
            touchwin(stdscr);
            refresh();
	    break;
      case KEY_F(2):
            menu_items=draw_menu2(20);
            selected_item=scroll_menu(menu_items,ntext);
            delete_menu(menu_items,ntext);
            if (selected_item<0)
                ;
            else
		send_stored_text(selected_item+1); 
            touchwin(stdscr);
            refresh();
	    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;
}

Note: The menu part of the code is from
http://www.linuxfocus.org/English/March2002/article233.shtml

Leave a comment