head 4.4; access ; symbols ; locks oasisa:4.4; strict; comment @ * @; 4.4 date 2001.06.19.12.12.42; author oasisa; state Exp; branches ; next ; desc @New Repository; 6/19/2001 (klh) @ 4.4 log @New Repository; 6/19/2001 (klh) @ text @/****************************************************************************/ /* Copyright 1991 MBARI */ /****************************************************************************/ /* $Header: clock.c,v 1.1 2001/06/19 11:42:42 oasisa Exp $ */ /* Summary : Support Routines for 68HC68 Clock Chip for OASIS Mooring */ /* Filename : clock.c */ /* Author : Robert Herlien (rah) */ /* Project : OASIS Mooring Controller */ /* $Revision: 1.1 $ */ /* Created : 02/12/91 */ /* */ /* MBARI provides this documentation and code "as is", with no warranty, */ /* express or implied, of its quality or consistency. It is provided without*/ /* support and without obligation on the part of the Monterey Bay Aquarium */ /* Research Institute to assist in its use, correction, modification, or */ /* enhancement. This information should not be published or distributed to */ /* third parties without specific written permission from MBARI. */ /* */ /* Archived : */ /****************************************************************************/ /* Modification History: */ /* 12feb91 rah - created */ /* $Log: clock.c,v $ * Revision 1.1 2001/06/19 11:42:42 11:42:42 oasisa (Oasis users) * Initial revision * * Revision 4.1 98/05/12 09:35:08 09:35:08 bobh (Bob Herlien) * June '98 turnaround for EqPac * * Revision 3.9 97/10/28 13:59:46 13:59:46 bobh (Bob Herlien) * EqPac Deployment of Nov 1997 * * Revision 3.5 96/07/17 13:01:24 13:01:24 bobh (Bob Herlien) * July '96 deployment of M2 with ARGOS code * * Revision 3.4 96/06/18 15:24:18 15:24:18 bobh (Bob Herlien) * June '96 deployment of M1 * * Revision 3.3 95/04/13 13:46:52 13:46:52 hebo (Bob Herlien) * Drifter Deployment for Coop (flip) cruise * * Revision 3.0 95/02/21 18:42:40 18:42:40 hebo (Bob Herlien) * February '95 Deployment * * Revision 2.0 92/08/21 14:44:23 14:44:23 hebo (Bob Herlien) * August 1992 deployment * * Revision 1.3 92/03/03 16:40:33 16:40:33 hebo (Bob Herlien 408-647-3748) * New defaults, restart check, perm power stuff, analog command * */ /****************************************************************************/ /* This module uses the Unix epoch day (day 0) of Jan 1, 1970. The real-time*/ /* clock chip only gives 2 decimal digits of year. Therefore, these */ /* routines assume that the year is between 1970 and 2069. Note that the */ /* leap-year exception for centuries not divisible by 400 is not a factor */ /* in this period. */ /****************************************************************************/ #include /* MBARI type definitions */ #include /* MBARI constants */ #include /* OASIS controller definitions */ #include /* OASIS I/O definitions */ #include <80c196.h> /* 80196 Register mapping */ #define RTC_RAM 0 /* RTC RAM at address 0 - 0x1f */ #define RTC_TIME 0x20 /* RTC time at 0x20 - 0x26 */ #define RTC_ALARM 0x28 /* RTC Alarm at 0x28 - 0x2a */ #define RTC_STATUS 0x30 /* RTC status reg */ #define RTC_CCR 0x31 /* RTC clock ctrl reg */ #define RTC_ICR 0x32 /* RTC interrupt ctrl reg */ #define RTC_WRITE 0x80 /* Write/~Read bit in address byte */ #define RTC_ALARM_BIT 0x10 /* Alarm bit in RTC_ICR */ #define RTC_PWR_DOWN 0x40 /* Power-down bit in RTC_ICR */ #define RTC_ALARM_INT_BIT 0x2 /* Alarm bit in RTC_STATUS */ #define RTC_OK 0x5a /* Arbitrary pattern to write @@ init*/ #define RTC_CCR_INIT 0xb5 /* CCR init: Run, 32KHz clk, 1Hz out*/ #define RTC_CCR_STOP 0x34 /* CCR stop: 32KHz clk, stop, no out*/ #define RTC_SECS (RTC_TIME) #define RTC_MIN (RTC_TIME + 1) #define RTC_HRS (RTC_TIME + 2) #define RTC_DATE (RTC_TIME + 4) #define RTC_MONTH (RTC_TIME + 5) #define RTC_YEAR (RTC_TIME + 6) #define RTC_ALARM_SECS (RTC_ALARM) #define RTC_ALARM_MIN (RTC_ALARM + 1) #define RTC_ALARM_HRS (RTC_ALARM + 2) /********************************/ /* External Data */ /********************************/ Extern Reg Byte port1_copy; /* Port 1 bits */ Extern Int16 gmtOffset; /* Local offset from GMT */ /********************************/ /* Global Data */ /********************************/ Global Reg TimeOfDay tod; /* Current time in TimeOfDay format */ Global Reg DateTime dttm; /* Current date & time in DateTime */ Global Reg Byte localHour; /* Hour of day (0 - 23) in local time*/ /********************************/ /* Module Local Data */ /********************************/ const Nat16 jdays[12] = /* Days since Jan. 1 in non-leap yr */ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; /************************************************************************/ /* Function : rtc_select */ /* Purpose : Select/Deselect RTC chip */ /* Input : TRUE to select, FALSE to deselect */ /* Outputs : None */ /************************************************************************/ Void rtc_select( MBool on ) { port1_copy &= ~(RTC_OUT); if ( on ) port1_copy |= (RTC_SI | RTC_SEL); ioport1 = port1_copy; } /* rtc_select() */ /************************************************************************/ /* Function : rtc_io */ /* Purpose : Read/write one byte to/from RTC chip */ /* Input : Byte to write to RTC */ /* Outputs : Byte read from RTC */ /* Comments : Takes approx 320 microseconds at 6.144 MHz */ /************************************************************************/ Byte rtc_io( Byte out ) { Reg Int8 i; Reg Byte in; for ( i = in = 0; i < 8; i++ ) { in <<= 1; if ( out & 0x80 ) port1_copy |= RTC_SO; else port1_copy &= ~RTC_SO; ioport1 = port1_copy | RTC_CLK; ioport1 = port1_copy; if ( ioport1 & RTC_SI ) in |= 1; out <<= 1; } return( (Word)in ); } /* rtc_io() */ /************************************************************************/ /* Function : rtc_write */ /* Purpose : Write one byte to RTC chip */ /* Inputs : Address, byte to write */ /* Outputs : None */ /************************************************************************/ Void rtc_write( Byte addr, Byte out ) { rtc_select( TRUE ); /* Select RTC chip */ rtc_io( addr | RTC_WRITE ); /* Put out address */ rtc_io( out ); /* Put out data */ rtc_select( FALSE ); /* Deselect RTC chip */ } /* rtc_write() */ /************************************************************************/ /* Function : rtc_read */ /* Purpose : Read one byte from RTC chip */ /* Inputs : Address to read */ /* Outputs : Value read */ /************************************************************************/ Byte rtc_read( Byte addr ) { Byte in; rtc_select( TRUE ); /* Select RTC chip */ rtc_io( addr ); /* Put out address */ in = rtc_io( 0 ); /* Read data */ rtc_select( FALSE ); /* Deselect RTC chip */ return( in ); } /* rtc_read() */ /************************************************************************/ /* Function : clk_status */ /* Purpose : Get RTC Status byte */ /* Inputs : None */ /* Output : RTC Status byte */ /************************************************************************/ Word clk_status( Void ) { return( rtc_read(RTC_STATUS) ); } /* clk_status() */ /************************************************************************/ /* Function : ep_days */ /* Purpose : Calculate number days since epoch (1/1/70) */ /* Inputs : Year - YEAR0, month, day of month */ /* Outputs : Days since 1/1/1990 */ /* Comment : The (year + 2)/4 term accounts for leap years, the */ /* first of which is 1972 (year - YEAR0 == 2) */ /************************************************************************/ Nat16 ep_days( Nat16 year, Nat16 month, Nat16 day ) { Reg Nat16 leap; leap = (month > 2) ? ((year + 2)/4) : ((year + 1)/4); return( (365 * year) + jdays[month-1] + leap + day - 1 ); } /* ep_days() */ /************************************************************************/ /* Function : bcd_to_hex */ /* Purpose : BCD to hex conversion */ /* Input : BCD byte */ /* Outputs : Hex byte or ERROR */ /************************************************************************/ Int16 bcd_to_hex( Nat16 byte ) { Reg Byte lownib, highnib; lownib = byte & 0xf; highnib = (byte>>4) & 0xf; if ( (lownib >= 10) || (highnib >= 10) ) return( ERROR ); return( (10 * highnib) + lownib ); } /* bcd_to_hex() */ /************************************************************************/ /* Function : hex_to_bcd */ /* Purpose : Hex to BCD conversion */ /* Input : Hex byte */ /* Outputs : BCD byte */ /************************************************************************/ Byte hex_to_bcd( Byte byte ) { return( ((byte / 10) << 4) + (byte % 10) ); } /* hex_to_bcd() */ /************************************************************************/ /* Function : dtToTod */ /* Purpose : Convert DateTime format to TimeOfDay format */ /* Input : DateTime */ /* Outputs : TimeOfDay */ /************************************************************************/ TimeOfDay dtToTod( Reg DateTime *dtp ) { Reg Int16 yr; Reg Nat16 secs; yr = (Int16)dtp->dt_yr - YEAR0; while ( yr < 0 ) yr += 100; secs = (60 * dtp->dt_min) + dtp->dt_sec; return((SECS_PER_DAY * ep_days(yr, (Nat16)dtp->dt_mo, (Nat16)dtp->dt_day)) + (3600L * dtp->dt_hr) + secs); } /* dtToTod() */ /************************************************************************/ /* Function : clk_read */ /* Purpose : Read Time of Day from the RTC chip */ /* Input : None */ /* Outputs : Time of Day */ /* Side Effects: Fills in tod with TimeOfDay and dttm with DateTime */ /************************************************************************/ MBool clk_read( Void ) { Byte min; do { min = rtc_read( RTC_MIN ); /* Read minute first. If it changes*/ /* while reading rest, need to redo */ dttm.dt_yr = bcd_to_hex(rtc_read(RTC_YEAR)); dttm.dt_mo = bcd_to_hex(rtc_read(RTC_MONTH)); dttm.dt_day = bcd_to_hex(rtc_read(RTC_DATE)); dttm.dt_hr = bcd_to_hex(rtc_read(RTC_HRS)); dttm.dt_min = bcd_to_hex(min); dttm.dt_sec = bcd_to_hex(rtc_read(RTC_SECS)); } while ( min != rtc_read(RTC_MIN) ); tod = dtToTod( &dttm ); localHour = (dttm.dt_hr + gmtOffset + 24) % 24; if ( (dttm.dt_yr < 0) || (dttm.dt_mo <= 0) || (dttm.dt_mo > 12) || (dttm.dt_day <= 0) || (dttm.dt_day > 31) || (dttm.dt_hr < 0) || (dttm.dt_hr > 23) || (dttm.dt_min < 0) || (dttm.dt_min >= 60) || (dttm.dt_sec < 0) || (dttm.dt_sec >= 60) ) return( FALSE ); return( TRUE ); } /* clk_read() */ /************************************************************************/ /* Function : clk_write */ /* Purpose : Set Date and Time in RTC chip */ /* Input : Ptr to DateTime struct */ /* Outputs : None */ /************************************************************************/ Void clk_write( Reg DateTime *dtp ) { rtc_write( RTC_CCR, RTC_CCR_STOP ); rtc_write( RTC_YEAR, hex_to_bcd(dtp->dt_yr) ); rtc_write( RTC_MONTH, hex_to_bcd(dtp->dt_mo) ); rtc_write( RTC_DATE, hex_to_bcd(dtp->dt_day) ); rtc_write( RTC_HRS, hex_to_bcd(dtp->dt_hr) ); rtc_write( RTC_MIN, hex_to_bcd(dtp->dt_min) ); rtc_write( RTC_SECS, hex_to_bcd(dtp->dt_sec) ); rtc_write( RTC_CCR, RTC_CCR_INIT ); tod = dtToTod( dtp ); } /* clk_write() */ /************************************************************************/ /* Function : clk_init */ /* Purpose : Initialize RTC chip at power-up */ /* Input : None */ /* Outputs : TRUE if OK */ /************************************************************************/ MBool clk_init( Void ) { Byte ramOkByte; rtc_write( RTC_CCR, RTC_CCR_INIT ); rtc_write( RTC_ICR, 0 ); if ( !clk_read() ) { dttm.dt_yr = 99; dttm.dt_mo = 1; dttm.dt_day = 1; dttm.dt_hr = 0; dttm.dt_min = 0; dttm.dt_sec = 0; clk_write( &dttm ); } else if ( rtc_read(RTC_RAM) == RTC_OK ) return( TRUE ); rtc_write( RTC_RAM, RTC_OK ); return( FALSE ); } /* clk_init() */ /************************************************************************/ /* Function : clk_alarm */ /* Purpose : Set Alarm in RTC chip */ /* Input : Seconds until next alarm */ /* Outputs : None */ /* Comments : Assumes tod is current */ /************************************************************************/ Void clk_alarm( Reg Nat16 altime ) { Reg Nat16 minsec; Reg TimeOfDay alarmTime; if ( !clk_read() ) clk_init(); alarmTime = tod + ((altime < MAX_ALARM_TIME) ? altime : MAX_ALARM_TIME); minsec = (Nat16)(alarmTime % 3600); rtc_write( RTC_ICR, 0 ); rtc_write( RTC_ALARM_SECS, hex_to_bcd(minsec % 60) ); rtc_write( RTC_ALARM_MIN, hex_to_bcd(minsec / 60) ); rtc_write( RTC_ALARM_HRS, hex_to_bcd((Nat16)((alarmTime/3600) % 24)) ); clk_status(); /* Clear alarm status */ rtc_write( RTC_ICR, RTC_ALARM_BIT ); } /* clk_alarm() */ /************************************************************************/ /* Function : clk_pwrdown */ /* Purpose : Power Down RTC Chip */ /* Inputs : None */ /* Output : None */ /* Comments : Assumes Alarm time was set, sets alarm bit */ /************************************************************************/ Void clk_pwrdown( Void ) { rtc_write( RTC_ICR, RTC_ALARM_BIT | RTC_PWR_DOWN ); /* Power down OASIS*/ } /* clk_pwrdown() */ @