home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 5
/
ctrom5b.zip
/
ctrom5b
/
CT
/
CT9404
/
TTDEMO
/
SOURCE.ZIP
/
TTTIME.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-01
|
19KB
|
600 lines
/***********************************************
* tttime.c *
* Copyright (c) 1993 QQS - All rights reserved *
* This file is donated to the public domain *
* *
* version 1.0 September 9, 1992 *
* set PC clock to teletext time & date *
* last update: 1.3 October 7, 1993 *
***********************************************/
/*
Note: Do not compile with Borland C 3.1 optimized for speed.
The hour = ... assignment in the interrupt may fail.
*/
#include <stdio.h>
#include <dos.h>
#include <time.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <dir.h>
#include <vector.h>
#include <tunefunc.h>
#include <tttest.h>
#define TRUE 1
#define FALSE 0
extern void interrupt TeletextInterrupt(void); // at end of file
#if 1 // set to 0 for english version
char* str_hi = "Fout: verkeerde -hi optie\n";
char* str_h = "Fout: verkeerde -h optie\n";
char* str_opts = "teveel opties aan elkaar in HARDWARE.INI";
char* str_optscfg = "teveel opties aan elkaar in TT.CFG";
char* str_card = "Geen teletext kaart gevonden!\n";
char* str_tune = "Fout bij initialiseren van tuner!\n";
char* str_settime = "\nTTTIME: computer tijd ingesteld op %02d:%02d:%02d\n";
char* str_setdate = "TTTIME: computer datum ingesteld op "
"%02d-%02d-%02d (dag-maand-jaar)\n";
char* str_notele = "\nTTTIME: geen teletext gevonden\n";
char* str_ver = "\nTTTIME 1.3 - stel computer tijd in op teletext tijd "
"(C) Oktober 1993 door QQS\n";
char* str_explain = "\nGebruik: TTTIME [-<optie><arg>...]\n"
"-<optie><arg>: -x<getal>; bepaal waarde\n\n"
"-<optie><standaard argument> beschrijving:\n"
"-t0 Tuner frequentie in Mhz, 0 -> directe video ingang\n"
"-hi11 decimale waarde voor Hardware IRQ lijn\n"
"-ha130 hexadecimale waarde voor Hardware start Adres\n\n"
"Als er geen parameters gegeven zijn, worden de parameters "
"geladen uit\nHARDWARE.INI en wordt het eerste kanaal in TT.CFG "
"geprobeerd.\nAls TT.CFG niet bestaat, wordt direct video "
"gebruikt.\n\n"
"Voorbeelden van gebruik:\n\n"
"TTTIME Gebruik HARDWARE.INI en eerste kanaal uit "
"TT.CFG\n\n"
"TTTIME -t189.25 Gebruik HARDWARE.INI en kanaal met frequentie "
"189.25 MHz\n"
" (alleen mogelijk met tuner).\n";
#else
char* str_hi = "Error: bad -hi switch\n";
char* str_h = "Error: bad -h switch\n";
char* str_opts = "Error: too many options concatenated in HARDWARE.INI";
char* str_optscfg = "Error: too many options concatenated in TT.CFG";
char* str_card = "No teletext card detected!\n";
char* str_tune = "Error initialising tuner!\n";
char* str_settime = "\nTTTIME: computer time set to %02d:%02d:%02d\n";
char* str_setdate = "TTTIME: computer date set to %02d-%02d-%02d "
"(dd-mm-yy)\n";
char* str_notele = "\nTTTIME: no teletext detected\n";
char* str_ver = "\nTTTIME 1.3 - set computer time to TeleText TIME "
"(C) October 1993 by QQS\n";
char* str_explain = "\nUsage: TTTIME [-<switch><arg>...]\n"
"-<switch><arg>: -x<value>; set value switch\n\n"
"-<switch><default arg> description:\n"
"-t0 Tuning frequency, 0 -> direct video\n"
"-hi11 decimal value for Hardware IRQ\n"
"-ha130 hexadecimal value for Hardware start Address\n\n"
"If no parameters are given, then parameters are loaded from "
"HARDWARE.INI and"
" first\nchannel in TT.CFG will be tried. If TT.CFG does not"
" exist, direct video\nwill be used.\n\nExamples of use:\n\n"
"TTTIME Use HARDWARE.INI and first channel from "
"TT.CFG\n\n"
"TTTIME -t189.25 Use HARDWARE.INI and channel with frequency "
"189.25 MHz\n(only possible with tuner).\n";
#endif
signed char Hamming[256]; /* translates hammingcodes, if Hamming[x] in 0..15 ->
Hamming[x] is value for x, Hamming[x] == -1 -> x is an error value. */
void InitHam(void)
/* init for hamming check (teletext control characters are hamming encoded) */
{
unsigned char valid[16] = {0x15, 0x02, 0x49, 0x5e, 0x64, 0x73, 0x38, 0x2f,
0xd0, 0xc7, 0x8c, 0x9b, 0xa1, 0xb6, 0xfd, 0xea}; // valid hammingcodes 0..15
int ii;
for(ii = 0; ii < 256; ii++)
Hamming[ii] = -1;
for(ii = 0; ii < 16; ii++)
Hamming[valid[ii]] = ii;
}
int OddParity[256]; // OddParity denotes whether char ii is odd
void InitOddParity(void)
/* init for odd parity (teletext characters should be odd parity) */
{
int ii;
for(ii = 0; ii < 256; ii++)
{
asm mov al,byte ptr [ii]
asm or al,al
asm jp even
OddParity[ii] = 1;
continue;
even:
OddParity[ii] = 0;
}
}
unsigned long tuneval = 0; // tune frequency (default = direct video)
unsigned int hardirq = 11, hardaddr = 0x130; // card address
char* homedir;
unsigned int homedirlen;
unsigned char oldmask; /* old interrupt mask */
void far* oldvector; /* old int vector */
void StartInt(void)
/* set interrupt for teletext */
{
unsigned char pat;
if(hardirq < 10)
{
oldvector = GetInterruptVector(hardirq + 8);
SetInterruptVector(hardirq + 8, TeletextInterrupt);
pat = ~(1 << hardirq);
asm in al,21h
asm mov [oldmask],al
asm and al, [pat] // enable hard int
asm out 21h,al
}
else
{
oldvector = GetInterruptVector(hardirq + 0x68);
SetInterruptVector(hardirq + 0x68, TeletextInterrupt);
pat = ~(1 << (hardirq - 8));
asm in al,0a1h
asm mov [oldmask],al
asm and al, [pat] // enable hard int
asm out 0a1h,al
}
outportb(hardaddr + 1, 0); // reset ram linenr & busybit
}
void StopInt(void)
/* restore setting of interrupt after teletext */
{
unsigned char pat;
outportb(hardaddr + 2, 0); // deselect tuner, int off
if(hardirq < 10)
{
pat = (1 << hardirq) & oldmask;
asm in al,21h
asm or al,[pat] // set bit int to old value
asm out 21h,al
SetInterruptVector(8 + hardirq, oldvector);
}
else
{
pat = (1 << (hardirq - 8)) & oldmask;
asm in al,0a1h
asm or al,[pat] // set bit int to old value
asm out 0a1h,al
SetInterruptVector(0x68 + hardirq, oldvector);
}
}
int loadarg(char* arg, int check)
/* load switches in arg, return whether ok. if check set ok to FALSE on strange
switches. */
{
int ok = TRUE;
int ch, ii;
long ll;
while(ok && *arg != '\0')
if(*arg == '/' || *arg == '-')
while(ok && *++arg != '\0' && *arg != ' ' && *arg != 0x9 && *arg != ',')
{
ch = tolower(*arg);
if(ch == 'h')
{
ch = tolower(*++arg);
if(ch == 'i')
{
for(ii = 0; *++arg >= '0' && *arg <= '9';)
ii *= 10, ii += *arg - '0';
--arg;
if(ii < 2 || ii > 15)
{
fprintf(stderr, str_hi);
ok = FALSE;
break;
}
if(ii == 9)
ii = 2; /* treat irq 9 as irq 2 */
hardirq = ii;
}
else
if(ch == 'a')
{
for(ii = 0; *++arg >= '0' && *arg <= '9' || *arg >= 'a' &&
*arg <= 'f' || *arg >= 'A' && *arg <= 'F';)
{
ii *= 16;
if(*arg >= '0' && *arg <= '9')
ii += *arg - '0';
else
if(*arg >= 'a' && *arg <= 'f')
ii += *arg - 'a' + 10;
else
ii += *arg - 'A' + 10;
}
--arg;
hardaddr = ii;
}
else
{
fprintf(stderr, str_h);
ok = FALSE;
break;
}
}
else
if(ch == 't')
{
for(ll = 0L; *++arg >= '0' && *arg <= '9';)
ll *= 10, ll += *arg - '0';
tuneval = ll * 1000000L;
if(*arg == '.')
{
for(ii = 0, ll = 0L; *++arg >= '0' && *arg <= '9';)
ii++, ll *= 10, ll += *arg - '0';
while(ii++ < 6)
ll *= 10;
tuneval += ll;
}
--arg;
}
else
if(check)
ok = FALSE;
else
if(ch == 'p')
arg += 2; // skip printer options
else
if(ch == 'v')
arg++; // skip video option
}
else
if(*arg == ' ' || *arg == 0x9 || *arg == ',')
arg++;
else
if(check)
ok = FALSE;
else
while(*arg != ',' && *arg != '\0' && *arg != ' ' && *arg != 0x9)
arg++;
return(ok);
}
void makename(char* filename, char* result)
/* set result to findable filename, search directories: ".", and homedir,
only search if name is not a path. if name nowhere found, set to "."
directory */
{
struct ffblk ffblk;
int len, ii;
strcpy(result, filename);
if(findfirst(result, &ffblk, 0) == 0)
return;
for(ii = 0; ii < strlen(filename); ii++)
if(filename[ii] == ':' || filename[ii] == '\\')
break;
if(ii < strlen(filename))
return; /* filename is path */
len = homedirlen + strlen(filename);
if(len >= 128)
return;
strcpy(result, homedir);
strcpy(result + homedirlen, filename);
if(findfirst(result, &ffblk, 0) == 0)
return;
strcpy(result, filename);
}
void skipspaces(FILE* in, unsigned int* linenr)
{
int ch;
for(;;)
switch(ch = getc(in))
{
case '#':
while(ch != '\n' && ch != EOF)
ch = getc(in);
case '\n':
(*linenr)++;
case ' ':
case 0x9: /* tab */
break;
default:
ungetc(ch, in);
return;
}
}
/* communication between program and interrupt must be via variables */
int year, month, day, hour, min, sec;
void main(int argc, char* argv[])
{
char name[150];
unsigned char remain;
int homedirlen;
FILE* file;
unsigned int ii, jj, linenr;
int ch;
int ok = TRUE;
clock_t starttime;
for(ii = 0; argv[0][ii] !='\0'; ii++)
if(argv[0][ii] == '\\')
homedirlen = ii + 1;
argv[0][homedirlen] = '\0';
homedir = argv[0];
fprintf(stderr, str_ver);
// load hardware.ini
makename("HARDWARE.INI", name);
if((file = fopen(name, "rt")) != NULL)
{
/* load switches from HARDWARE.INI */
ch = ' ';
while(ok && ch != EOF)
{
skipspaces(file, &ii);
if((ch = getc(file)) != EOF)
{
for(ii = 0; ii < 41 && ch != EOF && ch != ' ' && ch != 0x9 && ch !=
'#' && ch != '\n'; ii++, ch = getc(file))
name[ii] = ch;
if(ii == 41)
fprintf(stderr, str_opts);
ungetc(ch, file);
name[ii] = '\0';
if(ii != 0)
ok = loadarg(name, FALSE);
}
}
fclose(file);
}
if(argc <= 1)
{
// load first line of switches from TT.CFG
makename("TT.CFG", name);
if((file = fopen(name, "rt")) != NULL)
{
/* load first switches from tt.cfg */
ch = ' ';
linenr = 0;
skipspaces(file, &linenr);
jj = linenr;
while(ok && ch != EOF && jj == linenr)
{
if((ch = getc(file)) != EOF)
{
if(ch == '"')
{
do
ch = getc(file);
while(ch != '"' && ch != '\n' && ch != EOF);
ch = getc(file);
skipspaces(file, &linenr);
}
for(ii = 0; ii < 41 && ch != EOF && ch != ' ' && ch != 0x9 && ch !=
'#' && ch != '\n'; ii++, ch = getc(file))
name[ii] = ch;
if(ii == 41)
fprintf(stderr, str_optscfg);
ungetc(ch, file);
name[ii] = '\0';
ok = loadarg(name, FALSE);
}
skipspaces(file, &linenr);
}
fclose(file);
}
}
else // load given parameters
for(ii = 1; ok && ii < argc; ii++)
if(!loadarg(argv[ii], TRUE))
fputs("\n", stderr), ok = FALSE;
if(!ok)
fprintf(stderr, str_explain), exit(2);
if(!cardtest())
printf(str_card), exit(-1);
if(!InitTune())
printf(str_tune), exit(-1);
SelectChannel(tuneval);
hour = 25, month = 0, year = 100; /* teletext interrupt did not initialize */
starttime = clock(); /* wait at most 1 second for teletext */
InitHam();
InitOddParity();
StartInt();
remain = inportb(hardaddr + 2) & 0x2; // get tuner/video selection bit
outportb(hardaddr + 2, remain | 1); // interrupts on
while(clock() < starttime + CLK_TCK && hour == 25)
;
StopInt();
if(hour < 24 && min < 60 && sec < 60)
{
struct dostime_t time;
struct date date;
/* valid time */
time.hour = hour, time.minute = min, time.second = sec, time.hsecond = 0;
_dos_settime(&time);
printf(str_settime, hour, min, sec);
if(month != 0)
{
getdate(&date);
if(year != 100)
{
if((date.da_year + 1) % 100 == year)
date.da_year++;
else
date.da_year = (date.da_year / 100) * 100 + year;
}
else
if(month == 1 && date.da_mon == 12)
/* december -> january, increment year */
date.da_year++;
date.da_mon = month;
date.da_day = day;
setdate(&date);
printf(str_setdate, day, month, date.da_year % 100);
}
}
else
printf(str_notele);
}
/* teletext interrupt handler */
/* for interrupt handler no stack check and register vars, because place of
caller is unknown */
#pragma option -N- // no stack check
#pragma option -r- // no register vars
void interrupt TeletextInterrupt(void)
{
/* make sure to use only static variables here! */
static unsigned char buf[40]; // store header (line 0) here
static int semaphore = 0; // prevents interrupt overrun
static int numlines;
static unsigned char vidline; // television videoline with teletext
static int br, ag; // teletext control characters
static int line; // teletext line number
static struct
{
char* string;
int number;
} monthrow[14] = {{"jan", 1} , {"feb", 2}, {"mar", 3}, {"apr", 4}, {"may", 5},
{"mei", 5}, {"jun", 6}, {"jul", 7}, {"aug", 8}, {"sep", 9},
{"oct", 10}, {"okt", 10}, {"nov", 11}, {"dec", 12}};
static int index, testmonth; // counter and index in array
asm mov al,20h
asm out 20h, al // give end of interrupt
if(hardirq > 8)
{
asm mov al,20h
asm out 0a0h, al
}
if(semaphore)
return;
semaphore = TRUE;
asm sti
asm cld
numlines = inportb(hardaddr + 1) & 0x7f;
asm db 0ebh, 0 ; /* jmp short $+2, short wait */
outportb(hardaddr + 1, 0);
while(numlines > 0)
{
/* code handling one line */
vidline = inportb(hardaddr);
br = Hamming[inportb(hardaddr)];
ag = Hamming[inportb(hardaddr)];
if(br != -1 && ag != -1)
{
line = (br >> 3) + (ag << 1);
if(line == 0)
{
/* line 0 == header, time is in bytes 32..39 with format 12:34:56,
date can be anywhere in header */
for(index = 0; index < 40; index++)
{
buf[index] = inportb(hardaddr);
if(!OddParity[buf[index]])
break;
buf[index] &= 0x7f; // strip parity
if(buf[index] < 16)
buf[index] = ' '; // convert control to space
}
if(index == 40)
{
/* parity is ok */
hour = (buf[32] - '0') * 10 + buf[33] - '0';
min = (buf[35] - '0') * 10 + buf[36] - '0';
sec = (buf[38] - '0') * 10 + buf[39] - '0';
/* now scan for month in text format (e.g. 12 sep), this format is
used on NOS, BRT and BBC */
for(index = 10; index < 28; index++)
{
for(testmonth = 0; testmonth < 14; testmonth++)
/* test whether at index is month prefixed with day */
if(buf[index] == ' ' && buf[index + 4] == ' ' &&
buf[index - 1] >= '0' && buf[index - 1] <= '9' &&
(buf[index - 2] >= '0' && buf[index - 2] <= '9' ||
buf[index - 2] == ' ') &&
buf[index + 1] == monthrow[testmonth].string[0] &&
buf[index + 2] == monthrow[testmonth].string[1] &&
buf[index + 3] == monthrow[testmonth].string[2])
break;
if(testmonth != 14)
break;
}
if(index < 28)
{
/* date is found in text format */
month = monthrow[testmonth].number;
day = buf[index - 1] - '0';
if(buf[index - 2] != ' ')
day += (buf[index - 2] - '0') * 10;
}
else
{
/* scan for numerical format, used on german teletext,
e.g. 12.09.92 */
for(index = 8; index < 25; index++)
if((buf[index] >= '0' && buf[index] <= '9' || buf[index] == ' ')
&& buf[index + 1] >= '0' && buf[index + 1] <= '9' &&
buf[index + 3] >= '0' && buf[index + 3] <= '9' &&
buf[index + 4] >= '0' && buf[index + 4] <= '9' &&
buf[index + 6] >= '0' && buf[index + 6] <= '9' &&
buf[index + 7] >= '0' && buf[index + 7] <= '9')
break;
if(index < 25)
{
/* date is found in numerical format */
if(buf[index] != ' ')
day = (buf[index] - '0') * 10;
else
day = 0;
day += buf[index + 1] - '0';
month = (buf[index + 3] - '0') * 10 + buf[index + 4] - '0';
year = (buf[index + 6] - '0') * 10 + buf[index + 7] - '0';
}
}
}
}
}
--numlines, outportb(hardaddr, 0);
asm db 0ebh, 0 ; /* jmp short $+2, short wait */
}
outportb(hardaddr + 1, 0);
semaphore = FALSE;
}