home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 5 / ctrom5b.zip / ctrom5b / CT / CT9404 / TTDEMO / SOURCE.ZIP / TTTIME.C < prev    next >
C/C++ Source or Header  |  1994-02-01  |  19KB  |  600 lines

  1. /***********************************************
  2. * tttime.c                                     *
  3. * Copyright (c) 1993 QQS - All rights reserved *
  4. * This file is donated to the public domain    *
  5. *                                              *
  6. * version 1.0 September 9, 1992                *
  7. * set PC clock to teletext time & date         *
  8. * last update: 1.3 October 7, 1993             *
  9. ***********************************************/
  10.  
  11. /*
  12.     Note: Do not compile with Borland C 3.1 optimized for speed.
  13.           The hour = ... assignment in the interrupt may fail.
  14. */
  15.  
  16. #include <stdio.h>
  17. #include <dos.h>
  18. #include <time.h>
  19. #include <stdlib.h>
  20. #include <ctype.h>
  21. #include <string.h>
  22. #include <dir.h>
  23.  
  24. #include <vector.h>
  25. #include <tunefunc.h>
  26. #include <tttest.h>
  27.  
  28. #define TRUE  1
  29. #define FALSE 0
  30.  
  31. extern void interrupt TeletextInterrupt(void); // at end of file
  32.  
  33. #if 1 // set to 0 for english version
  34.  
  35.   char* str_hi = "Fout: verkeerde -hi optie\n";
  36.   char* str_h = "Fout: verkeerde -h optie\n";
  37.   char* str_opts = "teveel opties aan elkaar in HARDWARE.INI";
  38.   char* str_optscfg = "teveel opties aan elkaar in TT.CFG";
  39.   char* str_card = "Geen teletext kaart gevonden!\n";
  40.   char* str_tune = "Fout bij initialiseren van tuner!\n";
  41.   char* str_settime = "\nTTTIME: computer tijd ingesteld op %02d:%02d:%02d\n";
  42.   char* str_setdate = "TTTIME: computer datum ingesteld op "
  43.                                             "%02d-%02d-%02d (dag-maand-jaar)\n";
  44.   char* str_notele = "\nTTTIME: geen teletext gevonden\n";
  45.   char* str_ver = "\nTTTIME 1.3 - stel computer tijd in op teletext tijd   "
  46.                                                   "(C) Oktober 1993 door QQS\n";
  47.   char* str_explain = "\nGebruik: TTTIME [-<optie><arg>...]\n"
  48.           "-<optie><arg>:   -x<getal>; bepaal waarde\n\n"
  49.           "-<optie><standaard argument>  beschrijving:\n"
  50.           "-t0     Tuner frequentie in Mhz, 0 -> directe video ingang\n"
  51.           "-hi11   decimale waarde voor Hardware IRQ lijn\n"
  52.           "-ha130  hexadecimale waarde voor Hardware start Adres\n\n"
  53.           "Als er geen parameters gegeven zijn, worden de parameters "
  54.           "geladen uit\nHARDWARE.INI en wordt het eerste kanaal in TT.CFG "
  55.           "geprobeerd.\nAls TT.CFG niet bestaat, wordt direct video "
  56.           "gebruikt.\n\n"
  57.           "Voorbeelden van gebruik:\n\n"
  58.           "TTTIME             Gebruik HARDWARE.INI en eerste kanaal uit "
  59.                                                                     "TT.CFG\n\n"
  60.           "TTTIME -t189.25    Gebruik HARDWARE.INI en kanaal met frequentie "
  61.                                                                   "189.25 MHz\n"
  62.           "                   (alleen mogelijk met tuner).\n";
  63.  
  64. #else
  65.   char* str_hi = "Error: bad -hi switch\n";
  66.   char* str_h = "Error: bad -h switch\n";
  67.   char* str_opts = "Error: too many options concatenated in HARDWARE.INI";
  68.   char* str_optscfg = "Error: too many options concatenated in TT.CFG";
  69.   char* str_card = "No teletext card detected!\n";
  70.   char* str_tune = "Error initialising tuner!\n";
  71.   char* str_settime = "\nTTTIME: computer time set to %02d:%02d:%02d\n";
  72.   char* str_setdate = "TTTIME: computer date set to %02d-%02d-%02d "
  73.                                                                  "(dd-mm-yy)\n";
  74.   char* str_notele = "\nTTTIME: no teletext detected\n";
  75.   char* str_ver = "\nTTTIME 1.3 - set computer time to TeleText TIME   "
  76.                                                     "(C) October 1993 by QQS\n";
  77.   char* str_explain = "\nUsage: TTTIME [-<switch><arg>...]\n"
  78.       "-<switch><arg>:   -x<value>; set value switch\n\n"
  79.       "-<switch><default arg>  description:\n"
  80.       "-t0       Tuning frequency, 0 -> direct video\n"
  81.       "-hi11     decimal value for Hardware IRQ\n"
  82.       "-ha130    hexadecimal value for Hardware start Address\n\n"
  83.       "If no parameters are given, then parameters are loaded from "
  84.                                                               "HARDWARE.INI and"
  85.       " first\nchannel in TT.CFG will be tried. If TT.CFG does not"
  86.       " exist, direct video\nwill be used.\n\nExamples of use:\n\n"
  87.       "TTTIME             Use HARDWARE.INI and first channel from "
  88.                                                                     "TT.CFG\n\n"
  89.       "TTTIME -t189.25    Use HARDWARE.INI and channel with frequency "
  90.                                     "189.25 MHz\n(only possible with tuner).\n";
  91. #endif
  92.  
  93. signed char Hamming[256]; /* translates hammingcodes, if Hamming[x] in 0..15 ->
  94.     Hamming[x] is value for x, Hamming[x] == -1 -> x is an error value. */
  95.  
  96. void InitHam(void)
  97. /* init for hamming check (teletext control characters are hamming encoded) */
  98. {
  99.   unsigned char valid[16] = {0x15, 0x02, 0x49, 0x5e, 0x64, 0x73, 0x38, 0x2f,
  100.     0xd0, 0xc7, 0x8c, 0x9b, 0xa1, 0xb6, 0xfd, 0xea}; // valid hammingcodes 0..15
  101.   int ii;
  102.  
  103.   for(ii = 0; ii < 256; ii++)
  104.     Hamming[ii] = -1;
  105.   for(ii = 0; ii < 16; ii++)
  106.       Hamming[valid[ii]] = ii;
  107. }
  108.  
  109. int OddParity[256]; // OddParity denotes whether char ii is odd
  110.  
  111. void InitOddParity(void)
  112. /* init for odd parity (teletext characters should be odd parity) */
  113. {
  114.   int ii;
  115.  
  116.   for(ii = 0; ii < 256; ii++)
  117.   {
  118.     asm mov al,byte ptr [ii]
  119.     asm or al,al
  120.     asm jp even
  121.     OddParity[ii] = 1;
  122.     continue;
  123. even:
  124.     OddParity[ii] = 0;
  125.   }
  126. }
  127.  
  128. unsigned long tuneval = 0; // tune frequency (default = direct video)
  129. unsigned int hardirq = 11, hardaddr = 0x130; // card address
  130.  
  131. char* homedir;
  132. unsigned int homedirlen;
  133.  
  134. unsigned char oldmask; /* old interrupt mask */
  135. void far* oldvector; /* old int vector */
  136.  
  137. void StartInt(void)
  138. /* set interrupt for teletext */
  139. {
  140.   unsigned char pat;
  141.  
  142.   if(hardirq < 10)
  143.   {
  144.     oldvector = GetInterruptVector(hardirq + 8);
  145.     SetInterruptVector(hardirq + 8, TeletextInterrupt);
  146.     pat = ~(1 << hardirq);
  147.     asm in al,21h
  148.     asm mov [oldmask],al
  149.     asm and al, [pat]   // enable hard int
  150.     asm out 21h,al
  151.   }
  152.   else
  153.   {
  154.     oldvector = GetInterruptVector(hardirq + 0x68);
  155.     SetInterruptVector(hardirq + 0x68, TeletextInterrupt);
  156.     pat = ~(1 << (hardirq - 8));
  157.     asm in al,0a1h
  158.     asm mov [oldmask],al
  159.     asm and al, [pat]   // enable hard int
  160.     asm out 0a1h,al
  161.   }
  162.   outportb(hardaddr + 1, 0); // reset ram linenr & busybit
  163. }
  164.  
  165. void StopInt(void)
  166. /* restore setting of interrupt after teletext */
  167. {
  168.   unsigned char pat;
  169.  
  170.   outportb(hardaddr + 2, 0); // deselect tuner, int off
  171.   if(hardirq < 10)
  172.   {
  173.     pat = (1 << hardirq) & oldmask;
  174.     asm in al,21h
  175.     asm or al,[pat]     // set bit int to old value
  176.     asm out 21h,al
  177.     SetInterruptVector(8 + hardirq, oldvector);
  178.   }
  179.   else
  180.   {
  181.     pat = (1 << (hardirq - 8)) & oldmask;
  182.     asm in al,0a1h
  183.     asm or al,[pat]     // set bit int to old value
  184.     asm out 0a1h,al
  185.     SetInterruptVector(0x68 + hardirq, oldvector);
  186.   }
  187. }
  188.  
  189. int loadarg(char* arg, int check)
  190. /* load switches in arg, return whether ok. if check set ok to FALSE on strange
  191.    switches. */
  192. {
  193.   int ok = TRUE;
  194.   int ch, ii;
  195.   long ll;
  196.  
  197.   while(ok && *arg != '\0')
  198.     if(*arg == '/' || *arg == '-')
  199.       while(ok && *++arg != '\0' && *arg != ' ' && *arg != 0x9 && *arg != ',')
  200.       {
  201.         ch = tolower(*arg); 
  202.         if(ch == 'h')
  203.         {
  204.           ch = tolower(*++arg);
  205.           if(ch == 'i')
  206.           {
  207.             for(ii = 0; *++arg >= '0' && *arg <= '9';)
  208.               ii *= 10, ii += *arg - '0';
  209.             --arg;
  210.             if(ii < 2 || ii > 15)
  211.             {
  212.               fprintf(stderr, str_hi);
  213.               ok = FALSE;
  214.               break;
  215.             }
  216.             if(ii == 9)
  217.               ii = 2; /* treat irq 9 as irq 2 */
  218.             hardirq = ii;
  219.           }
  220.           else
  221.           if(ch == 'a')
  222.           {
  223.             for(ii = 0; *++arg >= '0' && *arg <= '9' || *arg >= 'a' &&
  224.                 *arg <= 'f' || *arg >= 'A' && *arg <= 'F';)
  225.             {
  226.               ii *= 16;
  227.               if(*arg >= '0' && *arg <= '9')
  228.                 ii += *arg - '0';
  229.               else
  230.               if(*arg >= 'a' && *arg <= 'f')
  231.                 ii += *arg - 'a' + 10;
  232.               else
  233.                 ii += *arg - 'A' + 10;
  234.             }
  235.             --arg;
  236.             hardaddr = ii;
  237.           }
  238.           else
  239.           {
  240.             fprintf(stderr, str_h);
  241.             ok = FALSE;
  242.             break;
  243.           }
  244.         }
  245.         else
  246.         if(ch == 't')
  247.         {
  248.           for(ll = 0L; *++arg >= '0' && *arg <= '9';)
  249.             ll *= 10, ll += *arg - '0';
  250.           tuneval = ll * 1000000L;
  251.           if(*arg == '.')
  252.           {
  253.             for(ii = 0, ll = 0L; *++arg >= '0' && *arg <= '9';)
  254.               ii++, ll *= 10, ll += *arg - '0';
  255.             while(ii++ < 6)
  256.               ll *= 10;
  257.             tuneval += ll;
  258.           }
  259.           --arg;
  260.         }
  261.         else
  262.         if(check)
  263.           ok = FALSE;
  264.         else
  265.         if(ch == 'p')
  266.           arg += 2; // skip printer options
  267.         else
  268.         if(ch == 'v')
  269.           arg++; // skip video option
  270.       }
  271.     else
  272.     if(*arg == ' ' || *arg == 0x9 || *arg == ',')
  273.       arg++;
  274.     else
  275.     if(check)
  276.       ok = FALSE;
  277.     else
  278.       while(*arg != ',' && *arg != '\0' && *arg != ' ' && *arg != 0x9)
  279.         arg++;
  280.   return(ok);
  281. }
  282.  
  283. void makename(char* filename, char* result)
  284. /* set result to findable filename, search directories: ".", and homedir,
  285.    only search if name is not a path. if name nowhere found, set to "."
  286.    directory */
  287. {
  288.   struct ffblk ffblk;
  289.   int len, ii;
  290.  
  291.   strcpy(result, filename);
  292.   if(findfirst(result, &ffblk, 0) == 0)
  293.     return;
  294.   for(ii = 0; ii < strlen(filename); ii++)
  295.     if(filename[ii] == ':' || filename[ii] == '\\')
  296.       break;
  297.   if(ii < strlen(filename))
  298.     return; /* filename is path */
  299.   len = homedirlen + strlen(filename);
  300.   if(len >= 128)
  301.     return;
  302.   strcpy(result, homedir);
  303.   strcpy(result + homedirlen, filename);
  304.   if(findfirst(result, &ffblk, 0) == 0)
  305.     return;
  306.   strcpy(result, filename);
  307. }
  308.  
  309. void skipspaces(FILE* in, unsigned int* linenr)
  310. {
  311.   int ch;
  312.  
  313.   for(;;)
  314.     switch(ch = getc(in))
  315.     {
  316.       case '#':
  317.         while(ch != '\n' && ch != EOF)
  318.           ch = getc(in);
  319.       case '\n':
  320.         (*linenr)++;
  321.       case ' ':
  322.       case 0x9: /* tab */
  323.         break;
  324.       default:
  325.         ungetc(ch, in);
  326.         return;
  327.     }
  328. }
  329.  
  330. /* communication between program and interrupt must be via variables */
  331. int year, month, day, hour, min, sec;
  332.  
  333. void main(int argc, char* argv[])
  334. {
  335.   char name[150];
  336.   unsigned char remain;
  337.   int homedirlen;
  338.   FILE* file;
  339.   unsigned int ii, jj, linenr;
  340.   int ch;
  341.   int ok = TRUE;
  342.   clock_t starttime;
  343.  
  344.   for(ii = 0; argv[0][ii] !='\0'; ii++)
  345.     if(argv[0][ii] == '\\')
  346.       homedirlen = ii + 1;
  347.   argv[0][homedirlen] = '\0';
  348.   homedir = argv[0];
  349.   fprintf(stderr, str_ver);
  350.   // load hardware.ini
  351.   makename("HARDWARE.INI", name);
  352.   if((file = fopen(name, "rt")) != NULL)
  353.   {
  354.     /* load switches from HARDWARE.INI */
  355.     ch = ' ';
  356.     while(ok && ch != EOF)
  357.     {
  358.       skipspaces(file, &ii);
  359.       if((ch = getc(file)) != EOF)
  360.       {
  361.         for(ii = 0; ii < 41 && ch != EOF && ch != ' ' && ch != 0x9 && ch !=
  362.           '#' && ch != '\n'; ii++, ch = getc(file))
  363.           name[ii] = ch;
  364.         if(ii == 41)
  365.           fprintf(stderr, str_opts);
  366.         ungetc(ch, file);
  367.         name[ii] = '\0';
  368.         if(ii != 0)
  369.           ok = loadarg(name, FALSE);
  370.       }
  371.     }
  372.     fclose(file);
  373.   }
  374.   if(argc <= 1)
  375.   {
  376.     // load first line of switches from TT.CFG
  377.     makename("TT.CFG", name);
  378.     if((file = fopen(name, "rt")) != NULL)
  379.     {
  380.       /* load first switches from tt.cfg */
  381.       ch = ' ';
  382.       linenr = 0;
  383.       skipspaces(file, &linenr);           
  384.       jj = linenr;
  385.       while(ok && ch != EOF && jj == linenr)
  386.       {
  387.         if((ch = getc(file)) != EOF)
  388.         {
  389.           if(ch == '"')
  390.           {
  391.             do
  392.               ch = getc(file);
  393.             while(ch != '"' && ch != '\n' && ch != EOF);
  394.             ch = getc(file);
  395.             skipspaces(file, &linenr);           
  396.           }
  397.           for(ii = 0; ii < 41 && ch != EOF && ch != ' ' && ch != 0x9 && ch !=
  398.               '#' && ch != '\n'; ii++, ch = getc(file))
  399.             name[ii] = ch;
  400.           if(ii == 41)
  401.             fprintf(stderr, str_optscfg);
  402.           ungetc(ch, file);
  403.           name[ii] = '\0';
  404.           ok = loadarg(name, FALSE);
  405.         }
  406.         skipspaces(file, &linenr);
  407.       }
  408.       fclose(file);
  409.     }
  410.   }
  411.   else // load given parameters
  412.     for(ii = 1; ok && ii < argc; ii++)
  413.       if(!loadarg(argv[ii], TRUE))
  414.         fputs("\n", stderr), ok = FALSE;
  415.   if(!ok)
  416.     fprintf(stderr, str_explain), exit(2);
  417.   if(!cardtest())
  418.     printf(str_card), exit(-1);
  419.   if(!InitTune())
  420.     printf(str_tune), exit(-1);
  421.   SelectChannel(tuneval);
  422.   hour = 25, month = 0, year = 100; /* teletext interrupt did not initialize */
  423.   starttime = clock(); /* wait at most 1 second for teletext */
  424.   InitHam();
  425.   InitOddParity();
  426.   StartInt();
  427.   remain = inportb(hardaddr + 2) & 0x2; // get tuner/video selection bit
  428.   outportb(hardaddr + 2, remain | 1); // interrupts on
  429.  
  430.   while(clock() < starttime + CLK_TCK && hour == 25)
  431.     ;
  432.   StopInt();
  433.   if(hour < 24 && min < 60 && sec < 60)
  434.   {
  435.     struct dostime_t time;
  436.     struct date date;
  437.  
  438.     /* valid time */
  439.     time.hour = hour, time.minute = min, time.second = sec, time.hsecond = 0;
  440.     _dos_settime(&time);
  441.     printf(str_settime, hour, min, sec);
  442.     if(month != 0)
  443.     {
  444.       getdate(&date);
  445.       if(year != 100)
  446.       {
  447.         if((date.da_year + 1)  % 100 == year)
  448.           date.da_year++;
  449.         else
  450.           date.da_year = (date.da_year / 100) * 100 + year;
  451.       }
  452.       else
  453.       if(month == 1 && date.da_mon == 12)
  454.         /* december -> january, increment year */
  455.         date.da_year++;
  456.       date.da_mon = month;
  457.       date.da_day = day;
  458.       setdate(&date);
  459.       printf(str_setdate, day, month, date.da_year % 100);
  460.     }
  461.   }
  462.   else
  463.     printf(str_notele);
  464. }
  465.  
  466. /* teletext interrupt handler */
  467.  
  468. /* for interrupt handler no stack check and register vars, because place of
  469.    caller is unknown */
  470. #pragma option -N-  // no stack check
  471. #pragma option -r-  // no register vars
  472.  
  473. void interrupt TeletextInterrupt(void)
  474. {
  475.   /* make sure to use only static variables here! */
  476.  
  477.   static unsigned char buf[40]; // store header (line 0) here
  478.  
  479.   static int semaphore = 0; // prevents interrupt overrun
  480.   static int numlines;
  481.  
  482.   static unsigned char vidline; // television videoline with teletext
  483.   static int br, ag; // teletext control characters
  484.   static int line; // teletext line number
  485.  
  486.   static struct
  487.   {
  488.     char* string;
  489.     int number;
  490.   } monthrow[14] = {{"jan", 1} , {"feb", 2}, {"mar", 3}, {"apr", 4}, {"may", 5},
  491.                     {"mei", 5}, {"jun", 6}, {"jul", 7}, {"aug", 8}, {"sep", 9},
  492.                     {"oct", 10}, {"okt", 10}, {"nov", 11}, {"dec", 12}};
  493.  
  494.   static int index, testmonth; // counter and index in array
  495.  
  496.   asm mov al,20h
  497.   asm out 20h, al  // give end of interrupt
  498.   if(hardirq > 8)
  499.   {
  500.     asm mov al,20h
  501.     asm out 0a0h, al
  502.   }
  503.   if(semaphore)
  504.     return;
  505.   semaphore = TRUE;
  506.   asm sti
  507.   asm cld
  508.   numlines = inportb(hardaddr + 1) & 0x7f;
  509.   asm db 0ebh, 0 ; /* jmp short $+2, short wait */
  510.   outportb(hardaddr + 1, 0);
  511.   while(numlines > 0)
  512.   {
  513.  
  514.     /* code handling one line */
  515.  
  516.     vidline = inportb(hardaddr);
  517.     br = Hamming[inportb(hardaddr)];
  518.     ag = Hamming[inportb(hardaddr)];
  519.     if(br != -1 && ag != -1)
  520.     {
  521.       line = (br >> 3) + (ag << 1);
  522.       if(line == 0)
  523.       {
  524.         /* line 0 == header, time is in bytes 32..39 with format 12:34:56,
  525.            date can be anywhere in header */
  526.         for(index = 0; index < 40; index++)
  527.         {
  528.           buf[index] = inportb(hardaddr);
  529.           if(!OddParity[buf[index]])
  530.             break;
  531.           buf[index] &= 0x7f; // strip parity
  532.           if(buf[index] < 16)
  533.             buf[index] = ' '; // convert control to space
  534.         }
  535.         if(index == 40)
  536.         {
  537.           /* parity is ok */
  538.           hour = (buf[32] - '0') * 10 + buf[33] - '0';
  539.           min = (buf[35] - '0') * 10 + buf[36] - '0';
  540.           sec = (buf[38] - '0') * 10 + buf[39] - '0';
  541.           /* now scan for month in text format (e.g. 12 sep), this format is
  542.              used on NOS, BRT and BBC */
  543.           for(index = 10; index < 28; index++)
  544.           {
  545.             for(testmonth = 0; testmonth < 14; testmonth++)
  546.               /* test whether at index is month prefixed with day */
  547.               if(buf[index] == ' ' && buf[index + 4] == ' ' &&
  548.                  buf[index - 1] >= '0' && buf[index - 1] <= '9' &&
  549.                  (buf[index - 2] >= '0' && buf[index - 2] <= '9' ||
  550.                  buf[index - 2] == ' ') &&
  551.                  buf[index + 1] == monthrow[testmonth].string[0] &&
  552.                  buf[index + 2] == monthrow[testmonth].string[1] &&
  553.                  buf[index + 3] == monthrow[testmonth].string[2])
  554.                 break;
  555.             if(testmonth != 14)
  556.               break;
  557.           }
  558.           if(index < 28)
  559.           {
  560.             /* date is found in text format */
  561.             month = monthrow[testmonth].number;
  562.             day = buf[index - 1] - '0';
  563.             if(buf[index - 2] != ' ')
  564.               day += (buf[index - 2] - '0') * 10;
  565.           }
  566.           else
  567.           {
  568.             /* scan for numerical format, used on german teletext, 
  569.                e.g. 12.09.92 */
  570.             for(index = 8; index < 25; index++)
  571.               if((buf[index] >= '0' && buf[index] <= '9' || buf[index] == ' ') 
  572.                  && buf[index + 1] >= '0' && buf[index + 1] <= '9' &&
  573.                  buf[index + 3] >= '0' && buf[index + 3] <= '9' &&
  574.                  buf[index + 4] >= '0' && buf[index + 4] <= '9' &&
  575.                  buf[index + 6] >= '0' && buf[index + 6] <= '9' &&
  576.                  buf[index + 7] >= '0' && buf[index + 7] <= '9')
  577.                 break;
  578.             if(index < 25)
  579.             {
  580.               /* date is found in numerical format */
  581.               if(buf[index] != ' ')
  582.                 day = (buf[index] - '0') * 10;
  583.               else
  584.                 day = 0;
  585.               day += buf[index + 1] - '0';
  586.               month = (buf[index + 3] - '0') * 10 + buf[index + 4] - '0';
  587.               year = (buf[index + 6] - '0') * 10 + buf[index + 7] - '0';
  588.             }
  589.           }
  590.         }
  591.       }
  592.     }
  593.  
  594.     --numlines, outportb(hardaddr, 0);
  595.     asm db 0ebh, 0 ; /* jmp short $+2, short wait */
  596.   }
  597.   outportb(hardaddr + 1, 0);
  598.   semaphore = FALSE;
  599. }
  600.