gclark@utcsri.UUCP (09/06/87)
Here is part 2 of my Amiga real-time clock design, containing the sources
for the clock software.
Graeme Clark -- Dept. of Computer Science, Univ. of Toronto, Canada M5S 1A4
{allegra,cornell,decvax,ihnp4,linus,utzoo}!utcsri!gclark
gclark@csri.toronto.edu
----------------- cut here -----------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# makefile
# clockwr.c
# clockrd.c
# clocktest.c
# nice_time.h
# This archive created: Sat Aug 29 19:59:54 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'makefile'" '(359 characters)'
if test -f 'makefile'
then
echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
# Makefile for clock programs, Manx 3.4a
clockrd : clockrd.o
ln -o clockrd clockrd.o -lc
clockwr : clockwr.o
ln -o clockwr clockwr.o -lc
clocktest : clocktest.o
ln -o clocktest clocktest.o -lc
clockrd.o : clockrd.c nice_time.h
cc clockrd.c
clockwr.o : clockwr.c nice_time.h
cc clockwr.c
clocktest.o : clocktest.c nice_time.h
cc clocktest.c
SHAR_EOF
if test 359 -ne "`wc -c < 'makefile'`"
then
echo shar: error transmitting "'makefile'" '(should have been 359 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'clockwr.c'" '(14906 characters)'
if test -f 'clockwr.c'
then
echo shar: will not over-write existing file "'clockwr.c'"
else
cat << \SHAR_EOF > 'clockwr.c'
#include <stdio.h>
#include <exec/types.h>
#include <hardware/custom.h>
#include <hardware/cia.h>
#include <resources/potgo.h>
#include <devices/timer.h>
#include <functions.h>
#include "nice_time.h"
/**********************************************************************
* clockwr -- prompt for the time and date, and set the hardware and *
* software clocks *
* usage: clockwr *
**********************************************************************/
main()
{
struct nice_time tm;
long seconds;
void set_time(), print_time(), term_port();
int init_port(), input_time(), check_time(), set_sys_time();
long nice_to_sec();
if (init_port() != 0)
exit(1);
if (input_time(&tm) != -1)
{
if (check_time(&tm) == -1)
{
printf("That doesn't look like a real date to me, so I'm\n");
printf("not going to bother to set the clocks.\n");
}
else
{
printf("Setting hardware clock..."); fflush(stdout);
set_time(&tm);
printf("\nSetting software clock..."); fflush(stdout);
seconds = nice_to_sec(&tm);
(void)set_sys_time(seconds);
printf("\nTime set to ");
print_time(&tm);
printf("Done.\n");
}
}
term_port();
}
/**********************************************************************
* input_time() -- prompt for the time and date and place in the *
* given nice_time structure *
* returns 0 normally, -1 if error *
**********************************************************************/
int input_time(tm)
struct nice_time *tm;
{
int get_int();
printf("If you goof or change your mind and don't want to set the\n");
printf("clocks, just press return\n");
printf("\n");
if ((tm->year = get_int("Year, e.g. 1986")) == -1)
return(-1);
if ((tm->month = get_int("Month (1..12)" )) == -1)
return(-1);
if ((tm->day = get_int("Day (1..31)" )) == -1)
return(-1);
if ((tm->day_of_week = get_int("Day of Week (0=Sun, ..., 6=Sat)")) == -1)
return(-1);
if ((tm->hour = get_int("Hour (0..23)" )) == -1)
return(-1);
if ((tm->minute = get_int("Minute (0..59)" )) == -1)
return(-1);
tm->second = 0;
return(0);
}
/**********************************************************************
* get_int() -- display the given prompt and read an integer, *
* returning it or -1 if a blank line is input *
**********************************************************************/
int get_int(prompt)
char *prompt;
{
char buf[80];
char *cp;
int atoi();
void getline();
printf("%s: ", prompt);
fflush(stdout);
getline(buf);
for (cp=buf; *cp == ' '; ++cp)
;
if (*cp == '\0')
return(-1);
else
return(atoi(cp));
}
/**********************************************************************
* getline() -- read a line from stdin *
**********************************************************************/
void getline(buf)
char *buf;
{
int ch;
while ((ch = getchar()) != '\n' && ch != EOF)
*buf++ = ch;
*buf = '\0';
}
/**********************************************************************
* print_time() -- display the contents of a nice_time structure *
**********************************************************************/
void print_time(tm)
struct nice_time *tm;
{
static char *mnames[12] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"};
static char *dnames[7] =
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
"Saturday"};
printf("%-9s %2d-%s-%02d %2d:%02d:%02d",
dnames[tm->day_of_week],
tm->day,
mnames[tm->month-1],
tm->year % 100,
(tm->hour==0) ? 12 : (tm->hour<=12) ? tm->hour :
tm->hour-12,
tm->minute,
tm->second);
if (tm->hour < 12)
printf(" AM\n");
else
printf(" PM\n");
}
/**********************************************************************
* nice_to_sec() -- convert the given nice_time structure into *
* seconds since 00:00:00 January 1, 1978 *
**********************************************************************/
long nice_to_sec(tm)
struct nice_time *tm;
{
long days_since_base;
static int mdays[] =
{
0,
0,
31,
31+28,
31+28+31,
31+28+31+30,
31+28+31+30+31,
31+28+31+30+31+30,
31+28+31+30+31+30+31,
31+28+31+30+31+30+31+31,
31+28+31+30+31+30+31+31+30,
31+28+31+30+31+30+31+31+30+31,
31+28+31+30+31+30+31+31+30+31+30
};
static int leapmdays[] =
{
0,
0,
31,
31+29,
31+29+31,
31+29+31+30,
31+29+31+30+31,
31+29+31+30+31+30,
31+29+31+30+31+30+31,
31+29+31+30+31+30+31+31,
31+29+31+30+31+30+31+31+30,
31+29+31+30+31+30+31+31+30+31,
31+29+31+30+31+30+31+31+30+31+30
};
/* first compute number of days since January 1, 1978 */
days_since_base = (tm->year-1978) * 365L + (tm->year-1977)/4;
if (tm->year%4 == 0)
days_since_base += leapmdays[tm->month];
else
days_since_base += mdays[tm->month];
days_since_base += tm->day-1;
/* now the rest is easy */
return(days_since_base * (60L*60L*24L) + tm->hour * (60L*60L) +
tm->minute * (60L) + tm->second);
}
/**********************************************************************
* set_sys_time() -- set the system time *
* Returns 0 normally, and -1 if an error occurs *
**********************************************************************/
int set_sys_time(secs)
long secs;
{
struct timerequest tr;
if (OpenDevice (TIMERNAME, UNIT_VBLANK, &tr, 0L) != 0L)
{
printf("Clock error: can't open timer device\n");
return(-1);
}
tr.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
tr.tr_node.io_Message.mn_Node.ln_Pri = 0L;
tr.tr_node.io_Message.mn_Node.ln_Name = NULL;
tr.tr_node.io_Message.mn_ReplyPort = NULL;
tr.tr_node.io_Command = TR_SETSYSTIME;
tr.tr_time.tv_secs = secs;
tr.tr_time.tv_micro = 0L;
if (DoIO (&tr) != 0)
{
printf("Clock error: can't talk to timer device\n");
CloseDevice(&tr);
return(-1);
}
CloseDevice (&tr);
return(0);
}
/**********************************************************************
* check_time() -- see if the given nice_time structure contains *
* reasonable values; return 0 if so, -1 otherwise *
**********************************************************************/
int check_time(tm)
struct nice_time *tm;
{
#define WITHIN(val, lower, upper) ((lower<=val) & (val<=upper))
if (WITHIN(tm->year, 1978, 1999) &&
WITHIN(tm->month, 1, 12) &&
WITHIN(tm->day, 1, 31) &&
WITHIN(tm->day_of_week, 0, 6) &&
WITHIN(tm->hour, 0, 23) &&
WITHIN(tm->minute, 0, 59) &&
WITHIN(tm->second, 0, 59))
return(0);
else
return(-1);
}
/*
* Variables for the clock routines
*/
struct Library *PotgoBase; /* points to Potgo Resource */
long potgo_bits; /* mask indicating which bits of the */
/* potgo resource we have allocated */
int held; /* 1 if the clock is currently stopped */
/**********************************************************************
* init_port -- initialize the joystick port (right game port) so *
* that we can talk to the clock *
* Returns 0 normally, and -1 if an error occurs *
**********************************************************************/
int init_port()
{
void pause();
/* open the Potgo resource so we can allocate ourselves the port */
PotgoBase = (struct Library *)OpenResource(POTGONAME);
if (PotgoBase == NULL)
{
printf("Clock error: can't open Potgo resource\n");
return(-1);
}
/* ask for the output bits of the right game port */
potgo_bits = AllocPotBits(0xF000L);
/* see if we got all the bits we asked for */
if (!((potgo_bits & 0x4000L) && (potgo_bits & 0x1000L)))
{
printf("Clock error: can't allocate gameport bits\n");
return(-1);
}
/* enable pins 5 and 9 for output, setting them both to 1 */
WritePotgo(0xF000L, 0xF000L);
pause(); /* wait for lines to settle */
held = 0; /* indicate clock not being held */
return(0);
}
/**********************************************************************
* term_port() -- release the game port *
**********************************************************************/
void term_port()
{
/* set pins 5 and 9 back to input mode */
WritePotgo(0x0000L, 0xF000L);
FreePotBits(potgo_bits);
/* I would think we should close the resource here, but */
/* CloseResource() doesn't seem to exist */
}
/**********************************************************************
* set_sclk() -- set the "SCLK" line high, by bringing pin 5 of the *
* game port low *
**********************************************************************/
void set_sclk()
{
void pause();
WritePotgo(0x0000L, 0x1000L);
pause();
}
/**********************************************************************
* clear_sclk() -- set the "SCLK" line low, by bringing pin 5 of *
* the game port high *
**********************************************************************/
void clear_sclk()
{
void pause();
WritePotgo(0x1000L, 0x1000L);
pause();
}
/**********************************************************************
* set_sdata() -- set the "SDATA" line high, by bringing pin 9 of *
* the game port low *
**********************************************************************/
void set_sdata()
{
void pause();
WritePotgo(0x0000L, 0x4000L);
pause();
}
/**********************************************************************
* clear_sdata() -- set the "SDATA" line low, by bringing pin 9 of *
* the game port high *
**********************************************************************/
void clear_sdata()
{
void pause();
WritePotgo(0x4000L, 0x4000L);
pause();
}
/**********************************************************************
* pause() -- delay for enough time for the gameport output lines *
* to settle. The RKM gives this time as 300 micro- *
* seconds, so to be on the safe side this routine *
* pauses for about 500 microseconds. *
* This routine depends on the CPU being a 68000 running *
* at 7.16 Mhz *
**********************************************************************/
void pause()
{
int i;
for (i=1; i<= 70; ++i)
;
}
/***********************************************************************
* send() -- send the given thirteen bits of data to the clock *
* curcuit. The bits in the data word are *
* *
* A3 A2 A1 A0 RD WBE HOLD WR D3 D2 D1 D0=S1 S2 *
* 12 11 10 9 8 7 6 5 4 3 2 1 0 *
* (MSB) (LSB) *
***********************************************************************/
void send(d)
int d;
{
int i;
/* shift the bits into the shift register */
for (i=1; i<=13; ++i)
{
if ((d & 1) == 1)
set_sdata();
else
clear_sdata();
set_sclk(); /* strobe the bit in */
if (i<13)
clear_sclk();
d >>= 1;
}
clear_sdata();
set_sdata(); /* latch the shift register contents */
clear_sclk();
}
/**********************************************************************
* write_reg() -- write the given value into the given register *
**********************************************************************/
void write_reg(r,v)
int r,v;
{
void send();
send(held<<6);
send((r<<9) | 0x080 | (held<<6) | (v<<1));
send((r<<9) | 0x0a0 | (held<<6) | (v<<1));
send((r<<9) | 0x080 | (held<<6) | (v<<1));
send(held<<6);
}
/**********************************************************************
* hold() -- stop the clock, and set the held flag so that the *
* clock will remain held while register reads or writes *
* are done *
**********************************************************************/
void hold()
{
held = 1;
send(0x040);
}
/**********************************************************************
* no_hold() -- restart the clock if it was held *
**********************************************************************/
void no_hold()
{
held = 0;
send(0x000);
}
/**********************************************************************
* set_time() -- set the clock *
**********************************************************************/
void set_time(tm)
struct nice_time *tm;
{
void hold(), nohold(), write_reg();
int leap_year, pm;
leap_year = (tm->year%4 == 0);
pm = (tm->hour >= 12);
hold();
write_reg(12, (tm->year%100)/10);
write_reg(11, tm->year%10);
write_reg(10, tm->month/10);
write_reg(9, tm->month%10);
write_reg(8, (tm->day/10) | (leap_year<<2));
write_reg(7, tm->day%10);
write_reg(6, tm->day_of_week);
write_reg(5, (tm->hour/10) | (pm<<2) | 8);
write_reg(4, tm->hour%10);
write_reg(3, tm->minute/10);
write_reg(2, tm->minute%10);
write_reg(1, tm->second/10);
write_reg(0, tm->second%10);
no_hold();
}
SHAR_EOF
if test 14906 -ne "`wc -c < 'clockwr.c'`"
then
echo shar: error transmitting "'clockwr.c'" '(should have been 14906 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'clockrd.c'" '(13617 characters)'
if test -f 'clockrd.c'
then
echo shar: will not over-write existing file "'clockrd.c'"
else
cat << \SHAR_EOF > 'clockrd.c'
/**********************************************************************
* clock.c -- read the time from the hardware clock, and set the *
* software clock to match. If the -d option is given, *
* the time is displayed as well. *
**********************************************************************/
#include <stdio.h>
#include <exec/types.h>
#include <hardware/cia.h>
#include <resources/potgo.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <devices/timer.h>
#include <functions.h>
#include "nice_time.h"
/**********************************************************************
* main program *
**********************************************************************/
main(argc, argv)
int argc;
char *argv[];
{
int dflag;
struct nice_time tm;
long seconds;
void term_port(), get_time(), print_time();
int init_port(), set_sys_time(), check_time();
long nice_to_sec();
dflag = 0;
if (argc == 2 && strcmp(argv[1], "-d") == 0)
dflag = 1;
if (init_port() != 0)
exit(1);
get_time(&tm); /* read the hardware clock */
term_port();
if (check_time(&tm) == -1) /* see if values reasonable */
{ /* (if not, the clock is not */
/* set or not there) */
printf("Clock error: clock contents not valid\n");
exit(1);
}
if (dflag)
print_time(&tm);
seconds = nice_to_sec(&tm); /* convert time to seconds since */
/* the base date */
(void)set_sys_time(seconds); /* set the software clock */
}
/*
* Variables for the clock routine
*/
struct Library *PotgoBase; /* points to Potgo Resource */
long potgo_bits; /* mask indicating which bits of the */
/* potgo resource we have allocated */
int held; /* 1 if the clock is currently stopped */
/**********************************************************************
* init_port -- initialize the joystick port (right game port) so *
* that we can talk to the clock *
* Returns 0 normally, and -1 if an error occurs *
**********************************************************************/
int init_port()
{
void pause();
/* open the Potgo resource so we can allocate ourselves the port */
PotgoBase = (struct Library *)OpenResource(POTGONAME);
if (PotgoBase == NULL)
{
printf("Clock error: can't open Potgo resource\n");
return(-1);
}
/* ask for the output bits of the right game port */
potgo_bits = AllocPotBits(0xF000L);
/* see if we got all the bits we asked for */
if (!((potgo_bits & 0x4000L) && (potgo_bits & 0x1000L)))
{
printf("Clock error: can't allocate gameport bits\n");
return(-1);
}
/* enable pins 5 and 9 for output, setting them both to 1 */
WritePotgo(0xF000L, 0xF000L);
pause(); /* wait for lines to settle */
held = 0; /* indicate clock not being held */
return(0);
}
/**********************************************************************
* term_port() -- release the game port *
**********************************************************************/
void term_port()
{
/* set pins 5 and 9 back to input mode */
WritePotgo(0x0000L, 0xF000L);
FreePotBits(potgo_bits);
/* I would think we should close the resource here, but */
/* CloseResource() doesn't seem to exist */
}
/**********************************************************************
* set_sclk() -- set the "SCLK" line high, by bringing pin 5 of the *
* game port low *
**********************************************************************/
void set_sclk()
{
void pause();
WritePotgo(0x0000L, 0x1000L);
pause();
}
/**********************************************************************
* clear_sclk() -- set the "SCLK" line low, by bringing pin 5 of *
* the game port high *
**********************************************************************/
void clear_sclk()
{
void pause();
WritePotgo(0x1000L, 0x1000L);
pause();
}
/**********************************************************************
* set_sdata() -- set the "SDATA" line high, by bringing pin 9 of *
* the game port low *
**********************************************************************/
void set_sdata()
{
void pause();
WritePotgo(0x0000L, 0x4000L);
pause();
}
/**********************************************************************
* clear_sdata() -- set the "SDATA" line low, by bringing pin 9 of *
* the game port high *
**********************************************************************/
void clear_sdata()
{
void pause();
WritePotgo(0x4000L, 0x4000L);
pause();
}
/**********************************************************************
* pause() -- delay for enough time for the gameport output lines *
* to settle. The RKM gives this time as 300 micro- *
* seconds, so to be on the safe side this routine *
* pauses for about 500 microseconds. *
* This routine depends on the CPU being a 68000 running *
* at 7.16 Mhz *
**********************************************************************/
void pause()
{
int i;
for (i=1; i<= 70; ++i)
;
}
/***********************************************************************
* send() -- send the given thirteen bits of data to the clock *
* curcuit. The bits in the data word are *
* *
* A3 A2 A1 A0 RD WBE HOLD WR D3 D2 D1 D0=S1 S2 *
* 12 11 10 9 8 7 6 5 4 3 2 1 0 *
* (MSB) (LSB) *
***********************************************************************/
void send(d)
int d;
{
int i;
/* shift the bits into the shift register */
for (i=1; i<=13; ++i)
{
if ((d & 1) == 1)
set_sdata();
else
clear_sdata();
set_sclk(); /* strobe the bit in */
if (i<13)
clear_sclk();
d >>= 1;
}
clear_sdata();
set_sdata(); /* latch the shift register contents */
clear_sclk();
}
/**********************************************************************
* read_reg() -- read and return the contents of the given register *
**********************************************************************/
int read_reg(r)
int r;
{
int data, bit0, bit1, bit2, bit3, i;
UWORD raw_data;
void send(), set_sclk(), clear_sclk();
/* macro to read the state of pin 6 of the port */
/* (ciaa is a macro defined in <hardware/cia.h>) */
#define READBIT ((ciaa.ciapra & CIAF_GAMEPORT1) != 0)
/* send the read command */
send((r<<9) | 0x10C | (held<<6));
/* read the data */
bit0 = READBIT;
set_sclk(); clear_sclk(); bit1 = READBIT;
set_sclk(); clear_sclk(); bit3 = READBIT;
set_sclk(); clear_sclk(); bit2 = READBIT;
data = (bit0 ) |
(bit1 << 1) |
(bit2 << 2) |
(bit3 << 3);
return(data);
}
/**********************************************************************
* hold() -- stop the clock, and set the held flag so that the *
* clock will remain held while register reads or writes *
* are done *
**********************************************************************/
void hold()
{
held = 1;
send(0x040);
}
/**********************************************************************
* no_hold() -- restart the clock if it was held *
**********************************************************************/
void no_hold()
{
held = 0;
send(0x000);
}
/**********************************************************************
* get_time() -- read the time from the clock and place it in a *
* nice_time structure. *
**********************************************************************/
void get_time(tm)
struct nice_time *tm;
{
void hold(), nohold();
int read_reg();
hold();
tm->year = 1900 + 10 * read_reg(12) + read_reg(11);
tm->month = 10 * (read_reg(10)&1) + read_reg(9);
tm->day = 10 * (read_reg(8)&3) + read_reg(7);
tm->day_of_week = read_reg(6);
tm->hour = 10 * (read_reg(5)&3) + read_reg(4);
tm->minute = 10 * (read_reg(3)&7) + read_reg(2);
tm->second = 10 * (read_reg(1)&7) + read_reg(0);
no_hold();
}
/**********************************************************************
* print_time() -- display the contents of a nice_time structure *
**********************************************************************/
void print_time(tm)
struct nice_time *tm;
{
static char *mnames[12] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"};
static char *dnames[7] =
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
"Saturday"};
printf("%-9s %2d-%s-%02d %2d:%02d:%02d",
dnames[tm->day_of_week],
tm->day,
mnames[tm->month-1],
tm->year % 100,
(tm->hour==0) ? 12 : (tm->hour<=12) ? tm->hour :
tm->hour-12,
tm->minute,
tm->second);
if (tm->hour < 12)
printf(" AM\n");
else
printf(" PM\n");
}
/**********************************************************************
* nice_to_sec() -- convert the given nice_time structure into *
* seconds since 00:00:00 January 1, 1978 *
**********************************************************************/
long nice_to_sec(tm)
struct nice_time *tm;
{
long days_since_base;
static int mdays[] =
{
0,
0,
31,
31+28,
31+28+31,
31+28+31+30,
31+28+31+30+31,
31+28+31+30+31+30,
31+28+31+30+31+30+31,
31+28+31+30+31+30+31+31,
31+28+31+30+31+30+31+31+30,
31+28+31+30+31+30+31+31+30+31,
31+28+31+30+31+30+31+31+30+31+30
};
static int leapmdays[] =
{
0,
0,
31,
31+29,
31+29+31,
31+29+31+30,
31+29+31+30+31,
31+29+31+30+31+30,
31+29+31+30+31+30+31,
31+29+31+30+31+30+31+31,
31+29+31+30+31+30+31+31+30,
31+29+31+30+31+30+31+31+30+31,
31+29+31+30+31+30+31+31+30+31+30
};
/* first compute number of days since January 1, 1978 */
days_since_base = (tm->year-1978) * 365L + (tm->year-1977)/4;
if (tm->year%4 == 0)
days_since_base += leapmdays[tm->month];
else
days_since_base += mdays[tm->month];
days_since_base += tm->day-1;
/* now the rest is easy */
return(days_since_base * (60L*60L*24L) + tm->hour * (60L*60L) +
tm->minute * (60L) + tm->second);
}
/**********************************************************************
* set_sys_time() -- set the system time *
* Returns 0 normally, and -1 if an error occurs *
**********************************************************************/
int set_sys_time(secs)
long secs;
{
struct timerequest tr;
if (OpenDevice (TIMERNAME, UNIT_VBLANK, &tr, 0L) != 0L)
{
printf("Clock error: can't open timer device\n");
return(-1);
}
tr.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
tr.tr_node.io_Message.mn_Node.ln_Pri = 0L;
tr.tr_node.io_Message.mn_Node.ln_Name = NULL;
tr.tr_node.io_Message.mn_ReplyPort = NULL;
tr.tr_node.io_Command = TR_SETSYSTIME;
tr.tr_time.tv_secs = secs;
tr.tr_time.tv_micro = 0L;
if (DoIO (&tr) != 0)
{
printf("Clock error: can't talk to timer device\n");
CloseDevice(&tr);
return(-1);
}
CloseDevice (&tr);
return(0);
}
/**********************************************************************
* check_time() -- see if the given nice_time structure contains *
* reasonable values; return 0 if so, -1 otherwise *
**********************************************************************/
int check_time(tm)
struct nice_time *tm;
{
#define WITHIN(val, lower, upper) ((lower<=val) & (val<=upper))
if (WITHIN(tm->year, 1978, 1999) &&
WITHIN(tm->month, 1, 12) &&
WITHIN(tm->day, 1, 31) &&
WITHIN(tm->day_of_week, 0, 6) &&
WITHIN(tm->hour, 0, 23) &&
WITHIN(tm->minute, 0, 59) &&
WITHIN(tm->second, 0, 59))
return(0);
else
return(-1);
}
SHAR_EOF
if test 13617 -ne "`wc -c < 'clockrd.c'`"
then
echo shar: error transmitting "'clockrd.c'" '(should have been 13617 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'clocktest.c'" '(13473 characters)'
if test -f 'clocktest.c'
then
echo shar: will not over-write existing file "'clocktest.c'"
else
cat << \SHAR_EOF > 'clocktest.c'
#include <stdio.h>
#include <exec/types.h>
#include <hardware/custom.h>
#include <hardware/cia.h>
#include <resources/potgo.h>
#include <functions.h>
#include "nice_time.h"
/**********************************************************************
* Clock hardware testing program *
* accepts the commands *
* sd set the SDATA line high *
* cd set the SDATA line low *
* sc set the SCLK line high *
* cc set the SCLK line low *
* send num send and latch the given 13-bit value (num in hex) *
* read reg read the indicated register (reg in hex) *
* write r v write v into register r (r and v in hex) *
* hold stop the clock *
* nohold restart the clock *
* get get and display the time *
* set y m d dw h m s set the time *
* e.g. set 1987 3 7 6 20 43 00 for Saturday March y, 1987 *
* 8:43 PM *
* quit exit the program *
**********************************************************************/
main()
{
char buf[800];
int d, r;
void getline(), term_port(), set_sclk(), set_sdata(),
clear_sclk(), clear_sdata(), send(), write_reg(),
hold(), no_hold(), get_time(), set_time(), print_time();
int init_port(), read_reg();
printf("Clock testing program\n");
if (init_port() != 0)
exit(1);
for (;;)
{
printf("Command: ");
fflush(stdout);
getline(buf);
if (strcmp(buf, "quit") == 0)
break;
else if (strcmp(buf, "sd") == 0)
set_sdata();
else if (strcmp(buf, "cd") == 0)
clear_sdata();
else if (strcmp(buf, "sc") == 0)
set_sclk();
else if (strcmp(buf, "cc") == 0)
clear_sclk();
else if (strncmp(buf, "send", 4) == 0)
{
sscanf(buf+4, "%x", &d);
send(d);
}
else if (strncmp(buf, "read", 4) == 0)
{
sscanf(buf+4, "%x", &r);
d = read_reg(r);
printf("Register %x contains %x\n", r, d);
}
else if (strncmp(buf, "write", 5) == 0)
{
sscanf(buf+5, "%x %x", &r, &d);
write_reg(r,d);
}
else if (strcmp(buf, "hold") == 0)
hold();
else if (strcmp(buf, "nohold") == 0)
no_hold();
else if (strcmp(buf, "get") == 0)
{
struct nice_time tm;
get_time(&tm);
print_time(&tm);
}
else if (strncmp(buf, "set", 3) == 0)
{
struct nice_time tm;
sscanf(buf+3, "%d %d %d %d %d %d %d",
&tm.year, &tm.month, &tm.day, &tm.day_of_week,
&tm.hour, &tm.minute, &tm.second);
set_time(&tm);
}
else
printf("Unknown comand\n");
}
term_port();
}
/**********************************************************************
* getline() -- read a line from stdin *
**********************************************************************/
void getline(buf)
char *buf;
{
int ch;
while ((ch = getchar()) != '\n' && ch != EOF)
*buf++ = ch;
*buf = '\0';
}
/*
* Variables for the clock routines
*/
struct Library *PotgoBase; /* points to Potgo Resource */
long potgo_bits; /* mask indicating which bits of the */
/* potgo resource we have allocated */
int held; /* 1 if the clock is currently stopped */
/**********************************************************************
* init_port -- initialize the joystick port (right game port) so *
* that we can talk to the clock *
* Returns 0 normally, and -1 if an error occurs *
**********************************************************************/
int init_port()
{
void pause();
/* open the Potgo resource so we can allocate ourselves the port */
PotgoBase = (struct Library *)OpenResource(POTGONAME);
if (PotgoBase == NULL)
{
printf("Clock error: can't open Potgo resource\n");
return(-1);
}
/* ask for the output bits of the right game port */
potgo_bits = AllocPotBits(0xF000L);
/* see if we got all the bits we asked for */
if (!((potgo_bits & 0x4000L) && (potgo_bits & 0x1000L)))
{
printf("Clock error: can't allocate gameport bits\n");
return(-1);
}
/* enable pins 5 and 9 for output, setting them both to 1 */
WritePotgo(0xF000L, 0xF000L);
pause(); /* wait for lines to settle */
held = 0; /* indicate clock not being held */
return(0);
}
/**********************************************************************
* term_port() -- release the game port *
**********************************************************************/
void term_port()
{
/* set pins 5 and 9 back to input mode */
WritePotgo(0x0000L, 0xF000L);
FreePotBits(potgo_bits);
/* I would think we should close the resource here, but */
/* CloseResource() doesn't seem to exist */
}
/**********************************************************************
* set_sclk() -- set the "SCLK" line high, by bringing pin 5 of the *
* game port low *
**********************************************************************/
void set_sclk()
{
void pause();
WritePotgo(0x0000L, 0x1000L);
pause();
}
/**********************************************************************
* clear_sclk() -- set the "SCLK" line low, by bringing pin 5 of *
* the game port high *
**********************************************************************/
void clear_sclk()
{
void pause();
WritePotgo(0x1000L, 0x1000L);
pause();
}
/**********************************************************************
* set_sdata() -- set the "SDATA" line high, by bringing pin 9 of *
* the game port low *
**********************************************************************/
void set_sdata()
{
void pause();
WritePotgo(0x0000L, 0x4000L);
pause();
}
/**********************************************************************
* clear_sdata() -- set the "SDATA" line low, by bringing pin 9 of *
* the game port high *
**********************************************************************/
void clear_sdata()
{
void pause();
WritePotgo(0x4000L, 0x4000L);
pause();
}
/**********************************************************************
* pause() -- delay for enough time for the gameport output lines *
* to settle. The RKM gives this time as 300 micro- *
* seconds, so to be on the safe side this routine *
* pauses for about 500 microseconds. *
* This routine depends on the CPU being a 68000 running *
* at 7.16 Mhz *
**********************************************************************/
void pause()
{
int i;
for (i=1; i<= 70; ++i)
;
}
/***********************************************************************
* send() -- send the given thirteen bits of data to the clock *
* circuit. The bits in the data word are *
* *
* A3 A2 A1 A0 RD WBE HOLD WR D3 D2 D1 D0=S1 S2 *
* 12 11 10 9 8 7 6 5 4 3 2 1 0 *
* (MSB) (LSB) *
***********************************************************************/
void send(d)
int d;
{
int i;
/* shift the bits into the shift register */
for (i=1; i<=13; ++i)
{
if ((d & 1) == 1)
set_sdata();
else
clear_sdata();
set_sclk(); /* strobe the bit in */
if (i<13)
clear_sclk();
d >>= 1;
}
clear_sdata();
set_sdata(); /* latch the shift register contents */
clear_sclk();
}
/**********************************************************************
* read_reg() -- read and return the contents of the given register *
**********************************************************************/
int read_reg(r)
int r;
{
int data, bit0, bit1, bit2, bit3, i;
UWORD raw_data;
void send(), set_sclk(), clear_sclk();
/* macro to read the state of pin 6 of the port */
/* (ciaa ia a macro defined in <hardware.cia.h>) */
#define READBIT ((ciaa.ciapra & CIAF_GAMEPORT1) != 0)
/* send the read command */
send((r<<9) | 0x10C | (held<<6));
/* read the data */
bit0 = READBIT;
set_sclk(); clear_sclk(); bit1 = READBIT;
set_sclk(); clear_sclk(); bit3 = READBIT;
set_sclk(); clear_sclk(); bit2 = READBIT;
data = (bit0 ) |
(bit1 << 1) |
(bit2 << 2) |
(bit3 << 3);
return(data);
}
/**********************************************************************
* write_reg() -- write the given value into the given register *
**********************************************************************/
void write_reg(r,v)
int r,v;
{
void send();
send(held<<6);
send((r<<9) | 0x080 | (held<<6) | (v<<1));
send((r<<9) | 0x0a0 | (held<<6) | (v<<1));
send((r<<9) | 0x080 | (held<<6) | (v<<1));
send(held<<6);
}
/**********************************************************************
* hold() -- stop the clock, and set the held flag so that the *
* clock will remain held while register reads or writes *
* are done *
**********************************************************************/
void hold()
{
held = 1;
send(0x040);
}
/**********************************************************************
* no_hold() -- restart the clock if it was held *
**********************************************************************/
void no_hold()
{
held = 0;
send(0x000);
}
/**********************************************************************
* get_time() -- read the time from the clock and place it in a *
* nice_time structure. *
**********************************************************************/
void get_time(tm)
struct nice_time *tm;
{
void hold(), nohold();
int read_reg();
hold();
tm->year = 1900 + 10 * read_reg(12) + read_reg(11);
tm->month = 10 * (read_reg(10)&1) + read_reg(9);
tm->day = 10 * (read_reg(8)&3) + read_reg(7);
tm->day_of_week = read_reg(6);
tm->hour = 10 * (read_reg(5)&3) + read_reg(4);
tm->minute = 10 * (read_reg(3)&7) + read_reg(2);
tm->second = 10 * (read_reg(1)&7) + read_reg(0);
no_hold();
}
/**********************************************************************
* print_time() -- display the contents of a nice_time structure *
**********************************************************************/
void print_time(tm)
struct nice_time *tm;
{
static char *mnames[12] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
"Oct", "Nov", "Dec"};
static char *dnames[7] =
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
"Saturday"};
printf("%-9s %2d-%s-%02d %2d:%02d:%02d",
dnames[tm->day_of_week],
tm->day,
mnames[tm->month-1],
tm->year % 100,
(tm->hour==0) ? 12 : (tm->hour<=12) ? tm->hour :
tm->hour-12,
tm->minute,
tm->second);
if (tm->hour < 12)
printf(" AM\n");
else
printf(" PM\n");
}
/**********************************************************************
* set_time() -- set the clock *
**********************************************************************/
void set_time(tm)
struct nice_time *tm;
{
void hold(), nohold(), write_reg();
int leap_year, pm;
leap_year = (tm->year%4 == 0);
pm = (tm->hour >= 12);
hold();
write_reg(12, (tm->year%100)/10);
write_reg(11, tm->year%10);
write_reg(10, tm->month/10);
write_reg(9, tm->month%10);
write_reg(8, (tm->day/10) | (leap_year<<2));
write_reg(7, tm->day%10);
write_reg(6, tm->day_of_week);
write_reg(5, (tm->hour/10) | (pm<<2) | 8);
write_reg(4, tm->hour%10);
write_reg(3, tm->minute/10);
write_reg(2, tm->minute%10);
write_reg(1, tm->second/10);
write_reg(0, tm->second%10);
no_hold();
}
SHAR_EOF
if test 13473 -ne "`wc -c < 'clocktest.c'`"
then
echo shar: error transmitting "'clocktest.c'" '(should have been 13473 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'nice_time.h'" '(409 characters)'
if test -f 'nice_time.h'
then
echo shar: will not over-write existing file "'nice_time.h'"
else
cat << \SHAR_EOF > 'nice_time.h'
/*
* nice_time.h -- a structure containing the time and date in a
* convenient form
*/
struct nice_time
{
int year; /* e.g. 1986 */
int month; /* 1...12 */
int day; /* 1...31 */
int day_of_week; /* 0(Sun)...6(Sat) */
int hour; /* 0...23 */
int minute; /* 0...59 */
int second; /* 0...59 */
} ;
SHAR_EOF
if test 409 -ne "`wc -c < 'nice_time.h'`"
then
echo shar: error transmitting "'nice_time.h'" '(should have been 409 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0