home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / hf / dsp / dsp4tool / dlcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-10  |  5.0 KB  |  203 lines

  1. /*  DLCMD.C -- Commands for DSP CARD 4 downloader
  2.  *
  3.  *  Copyright (C) by Alef Null 1992, 1993, 1994
  4.  *  Author(s): Jarkko Vuori, OH2LNS
  5.  *  Modification(s):
  6.  */
  7.  
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <malloc.h>
  12. #include <string.h>
  13. #include <time.h>
  14. #include <signal.h>
  15. #include "utils.h"
  16. #include "dl.h"
  17.  
  18.  
  19. #define RETRIES 3
  20.  
  21.  
  22. static int port = 1;
  23.  
  24. typedef enum {
  25.     PGM_FLASH,    // commands to DSP CARD
  26.     CHG_PGM,
  27.     READ_FLASH,
  28.     LOAD_GO,
  29.  
  30.     ACK,    // responses
  31.     BAD_CRC,
  32.     NO_FLASH,
  33.     ERASE_ERR,
  34.     PGM_ERR,
  35.     NO_PGM,
  36. } CardCommand;
  37.  
  38. const unsigned long wakeUp = 314159265; // special wake-up sequence
  39. const unsigned char flag   = 0x7e;    // msgblock flag byte (01111110)
  40.  
  41.  
  42. /*
  43.  * Wait (max 3s) for a character from the serial port
  44.  *
  45.  *  returns -1 if there is no character
  46.  */
  47. static int WaitSerial(void) {
  48.     unsigned long start;
  49.     int       c;
  50.  
  51.     #define BIOS_TIMER (volatile unsigned long far *)(0x46c)
  52.  
  53.     /* wait until timer changes its state */
  54.     start = *BIOS_TIMER;
  55.     while (start+54L != *BIOS_TIMER)     // 54.9ms*54=3s
  56.     if ((c = ReadSerial()) != -1)
  57.         return (c);
  58.  
  59.     return (-1);
  60. }
  61.  
  62. /*
  63.  * Wait for ACK from the DSP CARD 4
  64.  */
  65. static Bool waitAck(char *errortext[]) {
  66.     static char *errtxt[] = {
  67.     "Bad CRC",
  68.     "No FLASH EPROM chip on the board",
  69.     "FLASH EPROM erase error",
  70.     "FLASH EPROM program error",
  71.     "No such program"
  72.     };
  73.     static char unknownerr[80];
  74.     int c;
  75.  
  76.     if ((c = WaitSerial()) == -1) {
  77.     *errortext = "No response from the DSP CARD 4";
  78.     return (False);
  79.     }
  80.     if (c != ACK) {
  81.     if (c >= BAD_CRC && c < BAD_CRC+sizeof(errtxt)/sizeof(char *))
  82.         *errortext = errtxt[c-BAD_CRC];
  83.     else {
  84.         sprintf(unknownerr, "Unknown error code %d from the DSP CARD 4", c);
  85.         *errortext = unknownerr;
  86.     }
  87.  
  88.     return (False);
  89.     }
  90.  
  91.     return (True);
  92. }
  93.  
  94. /*
  95.  * Reset DSP CARD 4 and give a command to it
  96.  */
  97. static Bool giveCommand(CardCommand cmd) {
  98.     int   retryCount = 0;
  99.     char *errortext;
  100.  
  101.     /* first wake up DSP CARD */
  102.     while (retryCount++ < RETRIES) {
  103.     while (ReadSerial() != -1); // flush any garbage before possible ack
  104.     WriteSerial((int)(wakeUp >> 24)); WriteSerial((int)(wakeUp >> 16)); WriteSerial((int)(wakeUp >> 8)); WriteSerial((int)wakeUp);
  105.     if (!waitAck(&errortext))
  106.         continue;
  107.  
  108.     /* then send given command */
  109.     WriteSerial(cmd);
  110.     if (waitAck(&errortext))
  111.         return (True);
  112.     }
  113.  
  114.     fprintf(stderr, "%s\n", errortext);
  115.     return (False);
  116. }
  117.  
  118. /*
  119.  * Send one datablock to the DSP CARD 4
  120.  */
  121. static Bool sendBlock(BLKHEADER *pHeader, long huge *data) {
  122.     struct msgblk {
  123.     unsigned char flag;    // preamble
  124.     BLKHEADER     header;    // standard data block header
  125.     unsigned char data;    // data itself (continues after this block)
  126.     }          *msg;
  127.     unsigned   msglen, check;
  128.     int        retryCount = 0;
  129.     char      *errortext;
  130.  
  131.     /* first calculate the lenght of messageblock */
  132.     msglen = sizeof(struct msgblk)-sizeof(unsigned char)+3*pHeader->len+sizeof(unsigned);
  133.  
  134.     /* then setup message block */
  135.     if ((msg = (struct msgblk *)malloc(msglen)) != NULL) {
  136.     register long huge     *sp;
  137.     register unsigned char *dp;
  138.  
  139.     msg->flag   = flag;
  140.     msg->header = *pHeader;
  141.     /* copy the data itself (24-bit words to bytes) */
  142.     for (sp = data, dp = &msg->data; sp < &data[pHeader->len]; sp++) {
  143.         *dp++ = (unsigned char)(*sp >> 16);
  144.         *dp++ = (unsigned char)(*sp >> 8);
  145.         *dp++ = (unsigned char)*sp;
  146.     }
  147.     /* convert message block to big-endian format */
  148.     swab((char *)&msg->header.address, (char *)&msg->header.address, sizeof(unsigned)); swab((char *)&msg->header.len, (char *)&msg->header.len, sizeof(unsigned));
  149.     /* finally calculate the checkword */
  150.     check = ~crc((unsigned char *)msg, msglen-sizeof(unsigned));
  151.  
  152.     /* then send it */
  153.     while (retryCount++ < RETRIES) {
  154.         for (dp = (unsigned char *)msg; dp < (unsigned char *)msg+msglen-sizeof(unsigned); dp++)
  155.         WriteSerial(*dp);
  156.         WriteSerial(check); WriteSerial(check >> 8);
  157.  
  158.         /* then wait for ACK */
  159.         if (waitAck(&errortext)) {
  160.         free(msg);
  161.         return (True);
  162.         }
  163.     }
  164.  
  165.     fprintf(stderr, "%s\n", errortext);
  166.     free(msg);
  167.     }
  168.  
  169.     return (False);
  170. }
  171.  
  172. Bool cdecl setport(FILE *files[], int numArg) {
  173.     port = numArg;
  174.  
  175.     return (True);
  176. }
  177.  
  178. Bool cdecl loadandgo(FILE *files[]) {
  179.     static BLKHEADER termBlk = { p, 0, 0 };
  180.     Bool         fResult = True;
  181.  
  182.     /* we manipulate interrupt vectors in serial port handler, so ignore ctrl-c */
  183.     signal(SIGINT, (void (cdecl *)())SIG_IGN);
  184.     if (!OpenSerial(port, 9600)) {
  185.     fResult = False; goto endload;
  186.     }
  187.  
  188.     /* then download it to the DSP CARD 4 */
  189.     if (!giveCommand(LOAD_GO) || !ReadBlocks(files[0], sendBlock)) {
  190.     fResult = False; goto endload;
  191.     }
  192.  
  193.     /* finally start the program execution (by sending len=0 datablock) */
  194.     if (!sendBlock(&termBlk, NULL))
  195.     fResult = False;
  196.  
  197. endload:
  198.     CloseSerial();
  199.     signal(SIGINT, SIG_DFL);
  200.  
  201.     return (fResult);
  202. }
  203.