No Frames. Direct to: Dontronics Shop What's New? or Dontronics Shop

Dontronics Home Page   Real Time Clock

Table of Contents

RTC Prices: Includes pointers to code examples.

Basic Stamp 2. Program 1: To DS-1202 by Bob Martin.
Basic Stamp 2. Program 2: To DS-1202 by David Baker.
Basic Stamp 2. Program 3: To NJU-6355 by Craig Simmonds.
Basic Stamp 2. Program 4: To PCF8593P by Dragan Kujovic.
FED Basic Program: To DS-1302 by Mick Gulovsen.
PIC MicroChip Code: To DS-1202 by Mark Sullivan.
PIC MicroChip Code: To DS-1302 by John Sanderson.
DS-1202 problems: by Llewellyn Griffiths.
Interfacing the DS5000 to the DS1307 By Dallas Semiconductor
Check Additional Data on DS-1202/1302
DS1302 from port d on an 8535 (SIMM100), written in asm using AVRA assembler. by Ingmar Meins
 

Introduction

You can easily add a real time clock to most micros using only 3 signals. With careful selection, some pins can be shared with other devices.

 I have put together a clock/crystal combination that takes a bit of beating. The Dallas-Semiconductor DS1302 is an 8 pin DIP Trickle Charge Time Keeping Chip that uses a 32.768kHz crystal. This crystal should have a load capacitance of 6pf for reasonable accuracy.

 The DS1302 is an enhanced version of the DS1202. Pin 1 is now used to connect to an optional trickle charge for battery or supercap input. It also has 31 bytes of RAM, an extra 7 bytes over the DS1202.

 DS1302 in 8 pin DIP.
32.768kHz Crystal to suit.
Check RTC Prices

 Beware! These crystals are small, about the width of a very small tooth-pick and about 1/4" long, so don't loose it.

 As a working example, I have included in this file some programs I found on the Internet Stamp List, which may be enough get you started towards a result. And if you do get a result, please feedback is nice.

 I also have added the code that my friend Mick Gulovsen did using FED Basic and the DS-1302.

 The example has some additional overhead for speaker and LCD operation that needs to be weeded out and it's for the DS1202, so it doesn't take advantage of the DS1302 features, but should work straight up, as both devices are code and pin compatible with upward expansion for the DS1302.

 Back to the Table of Contents

BS-2 Program 1:

From rtm@newton.apple.com Fri Dec  8 17:50:41 1995

Date: Sun, 3 Dec 1995 14:31:55 -0800

From: Bob Martin 

Reply to: stamps@parallaxinc.com

To: NUNESJ@aol.com, stamps@parallaxinc.com

Subject: [STAMPS] Stamp II - time and date



Here's the source code for a simple LCD clock using the Stamp II and

the dallas semiconductor DS1202 clock chip. The Dallas chip is available

mail order from JDR Microdevices. You can get dallas semi spec sheets from

their web server at http://www.dalsemi.com

Cheers-

Bob Martin



' Bob's Clock for the Stamp II - DS120S

' Uses:

'      Dallas Semiconductor DS1202 clock chip

'      Optrex DMC-16207 16x2 LCD

'      Cheezy 2.5" speaker

' Last modified:

'      12/3/95 RTM 1200

' Stamp II I/O pins:

' 0 LCD 11      8 DS1202 5 rst*

' 1 LCD 12      9 DS1202 6 i/o

' 2 LCD 13     10 DS1202 7 clk

' 3 LCD 14     11

' 4 LCD 4      12

' 5 LCD 6      13 cheezy speaker thru 10uf

' 6            14

' 7            15



' I/O definitions

lcdrs  con     4       ' LCD register select

lcde   con     5       ' LCD enable pin

lcdbl  con     6       ' LCD backlight control

spkr   con     13      ' for a cheezy speaker



' Dallas Semiconductor DS1202 clock chip

dsrst  con     8       ' rst* pin 5 (normally low w 47k)

dsio   con     9       ' i/o  pin 6

dsclk  con     10      ' sclk pin 7 (pull low w 47k)



' Constants for addressing the DS1202 clock chip

dssec  con     $80     ' seconds register

dsmin  con     $82     ' minutes register

dshr   con     $84     ' hours register

dsdate con     $86     ' date

dsmon  con     $88     ' month

dsday  con     $8A     ' day of week, 1=sunday

dsyear con     $8C     ' year

dsctl  con     $8E     ' control register

dsram  con     $C0     ' start of ram (24 bytes)



' constants for lcd commands

posdate        con     $80 | 40        ' position to line 2

postime        con     $80 | 4         ' time hh:mm:ss starts here

possecs        con     $80 | 10        ' seconds (ss) starts here



' dsis is the initialisation string for the clock.

' consists of pairs . Note the first entries should

' write enable the clock and then stop it running, and the

' last entries should restart and write protect it!



dsis   data dsctl,0            ' write enable the clock

       data dssec,$80          ' stop clock, set secs to 00

       data dsyear,$95         ' year 1995

       data dsday,6            ' friday

       data dsmon,$12          ' december

       data dsdate,$1          ' 1

       data dshr,$20           ' 24 hour clock, 2000

       data dsmin,$04          ' 04 minutes

       data dssec,$00          ' start the clock running again

       data dsctl,$80          ' write protect the clock

       data 0,0                ' end of the list



' Day of week text (abbreviations) Each entry is 3 bytes

' plus a zero termination character. Sunday=1



dowt   data "RTM",0,"Sun",0,"Mon",0,"Tue",0

       data "Wed",0,"Thu",0,"Fri",0,"Sat",0



' variables used in the program

' these variables are copies of the DS1202 registers, and are

' updated as bytes- so you can't change dow to a nybble!



secs   var     byte    ' bcd seconds

mm     var     byte    ' bcd minutes

hh     var     byte    ' bcd hours

date   var     byte    ' bcd day of the month

month  var     byte    ' bcd month

dow    var     byte    ' day of the week, Sunday = 1

year   var     byte    ' bcd year



' general stuff



i      var     word    ' computational temp



dsaddr var     byte    ' ds1202 register address we're whacking

dsdata var     byte    ' and the data going back and forth

lcdchr var     byte    ' character sent to LCD

bcd    var     byte    ' bcd data sent to LCD



' Start here.



       low dsrst               ' make sure the reset* line is low

       low dsclk               ' same with the clock line

       nap 2                   ' wait for the world to settle

       gosub lcdinit           ' set up the display



'      gosub dsinit            ' set up the clock

'      gosub dsdbg



' Read data from the clock and display date and time



       gosub dsrd7             ' update time variables

       gosub tdisplay          ' update display



'      nap 6                   ' snooze a bit



' Top of the clock loop. We wait for the seconds to change,

' napping in low power mode between checking the clock



clock1:        nap 2                   ' delay at low power a while

       dsaddr = dssec          ' look at seconds register

       gosub dsread            ' read seconds register

       if dsdata = secs then clock1    ' wait if no change



clock2:        secs = dsdata           ' update our number



' tick-tock stuff with the speaker - tone flips between 400 and 800 hz

' based on the low bit of the seconds



       freqout spkr,30,400+(400*(secs & $01))



' When the seconds change, we only rewrite the seconds portion of

' the display.



clock4:        if secs = 0 then clock5         ' a minute has passed

       lcdchr = possecs

       bcd = secs

       gosub wrcb                      ' put out seconds

'      debug HEX secs,cr

       goto clock1                     ' loop



' secs=0, a minute has passed. update vars and rewrite whole display



clock5:        gosub dsrd7                     ' block read all 7 bytes

       gosub tdisplay                  ' display date and time

'      debug HEX2 hh,":",HEX2 mm,":00",cr



clock6:        if mm <> 0 then clock1          ' scram if not an hour



' We have reached an hour! Do something exciting!



clock7:



' Daylight savings time. I don't mind having to reset mechanical

' clocks when we go on and off dst, but if the thing has a calendar

' in it, it should be able to do daylight savings adjustments itself.



       if (hh=2) & (dow=1) & ((month=4)|(month=$10)) then ckdst



       goto clock1                     ' loop around



' Check for dalight savings time. We already know it is 2am on a

' Sunday in April or October- do the rest of the test and diddle

' the time if required.



ckdst: if (month=10) & (date>$24) then ckdstf  ' last Sun in Oct.

       if (month=4) & (date<8) then ckdsts     ' first Sun in April

       goto clock1                             ' not time to correct.



' Fall back - last Sunday in October



ckdstf:        hh=1

       goto ckdstu                     ' 1 AM and update it



' Spring forward - first Sunday in April



ckdsts:        hh=3                            ' 3 AM



ckdstu:        gosub dsenab                    ' write enable the clock

       dsdata=hh

       dsaddr=dshr

       gosub dswrite                   ' jam in new hour

       gosub dswp                      ' write protect the clock

       goto clock1                     ' loop



' tdisplay put hh:mm:ss on line 1 of the display,

' Put dow dd/mm/yy on the LCD in line 2, character position 40.



' The end of this routine shows another space saving trick- replacing

' a gosub xxxx/return sequence with goto xxxx.



tdisplay:

       if mm>0 then tdisp0

       lcdchr = $1

       gosub lcdcmd            ' clear display once per hour

       pause 1

tdisp0:        lcdchr = postime        ' put hh:mm:ss on display here

       bcd  = hh               ' so it lines up with the date

       gosub wrcb              ' displayed on line 2

       lcdchr = ":"            ' hh :

       bcd = mm

       gosub wrsb              ' hh:mm

       bcd = secs

       gosub wrsb              ' hh:mm:ss

       i = 4*dow               ' index into day of week text

       lcdchr= posdate         ' this is where line 2 starts

       gosub lcdcmd            ' position LCD cursor

tdisp1:        read dowt+i,lcdchr      ' get day of week text

       if lcdchr = 0 then tdisp2

       gosub wrlcd             ' put out that character

       i = i + 1

       goto tdisp1             ' loop until 00 byte hit

tdisp2: lcdchr = " "

       bcd = month

       gosub wrsb              ' dow mm

       lcdchr = "/"

       bcd = date

       gosub wrsb              ' dow mm/dd

       bcd = year

       goto wrsb               ' dow mm/dd/yy and return



' debug dump the contents of clock registers- about 48 bytes



'dsdbg:        for i=0 to 7

'      dsaddr = $80 | (i+i)    ' make a register address

'      gosub dsread            ' read its contents

'      debug "reg ",HEX i," = ",HEX dsdata,cr

'      next

'      return



' ram test - uses first ram location

'

' ram test pattern - walking 1 followed by walking 0

'

'dsrt  data 1,2,4,8,$10,$20,$40,$80

'      data $7F,$BF,$DF,$EF,$F7,$FB,$FD,$FE,0

'

'ramtest:

'      gosub dsenab                    ' write enable ram

'      i = 0                           ' index into rt data

'      dsaddr = dsram                  ' use this loc

'rt1:  read dsrt+i,dsdata

'      if dsdata = 0 then rtn          ' split when 00 hit

'      hh=dsdata                       ' save it off

'      gosub dswrite                   ' write it

'      gosub dsread

'      debug "wrote ",HEX hh," read ",HEX dsdata,cr

'      pause 700

'      i = i + 1

'      goto rt1



' set up the clock for a reasonable starting time



dsinit:        i = 0                           ' index into initialization data

dsi0:  read dsis + i,dsaddr            ' get address to stuff

       read dsis + 1 + i,dsdata        ' and data to put there

       if dsaddr = 0 then rtn          ' exit when 00 hit

       gosub dswrite                   ' write data to the clock

       i = i+2                         ' bump the pointer

       goto dsi0                       ' loop over the list



' read and write subroutines. uses dsaddr and dsdata

' specifying \8 doesn't cost anything in terms of memory use- even

' though it's the default, it's a good reminder to have it present...



dsread:

       dsaddr = dsaddr | 1                     ' make sure it's a read!

       high dsrst                              ' start read cycle

       shiftout dsio,dsclk,lsbfirst,[dsaddr\8] ' send address

       shiftin dsio,dsclk,lsbpre,[dsdata\8]    ' get the data

       low dsrst                               ' end read cycle

       return



' write enable and write protect the clock.

' clobbers dsaddr and dsdata



dsenab:        dsdata = 0      ' 0 to write enable

       goto dswp0      ' return through write protect code



dswp:  dsdata = $80    ' set the bit to write protect

dswp0: dsaddr = dsctl  ' control register, fall into dswrite



dswrite:

       dsaddr = dsaddr & $FE                   ' make sure a write

       high dsrst                              ' start cycle

       shiftout dsio,dsclk,lsbfirst,[dsaddr\8] ' send address

       shiftout dsio,dsclk,lsbfirst,[dsdata\8] ' send data

       low dsrst                               ' end cycle

       return



' block read clock vars- unfortunately, shiftin only does

' 16 bits at a shot, so I can't do all 56 bits at once



dsrd7: dsaddr = $BF                            ' clock burst

       high dsrst                              ' start the cycle

       shiftout dsio,dsclk,lsbfirst,[dsaddr\8]

       shiftin dsio,dsclk,lsbpre,[secs\8]      ' 8 for seconds

       shiftin dsio,dsclk,lsbpre,[mm\8]

       shiftin dsio,dsclk,lsbpre,[hh\8]

       shiftin dsio,dsclk,lsbpre,[date\8]

       shiftin dsio,dsclk,lsbpre,[month\8]

       shiftin dsio,dsclk,lsbpre,[dow\8]

       shiftin dsio,dsclk,lsbpre,[year\8]      ' thru 8 for year

       low dsrst

       return



' LCD support routines - should work with most LCDs using the same

' controller chip. Note that these routines use "pause" and not "nap"-

' we don't want the I/O pins going hi-Z on us...



' LCD init, 4 bit mode, stamp II pins 0-5



LCDinit:

       dirl = %00111111        ' lcd pins as outputs

       outl = 00               ' make 'em all low

       pause 200               ' 200 ms reset time for lcd!

       outa = %0011            ' 8 bit mode

       pulsout lcde,1

       pause 5

       pulsout lcde,1

       pulsout lcde,1          ' this insures 8 bit mode

       outa = %0010            ' now force 4 bit mode

       pulsout lcde,1

       lcdchr = $28            ' force 2 line mode

       gosub wrlcd

       lcdchr = $0C            ' display on, cursor off, blink off

       gosub wrlcd

       lcdchr = 6              ' autoincr cursor, no shift

       gosub wrlcd

       lcdchr = 1              ' clear lcd

       goto lcdcm0             ' exiting through common code



' Send command in lcdchr to the LCD - flip RS, send it, flip RS back.

' preserves lcdchr



' The label "rtn" on the return in this routine is used as a branch

' target in other places in the program to save code space.



lcdcmd:        low lcdrs               ' rs=0 for command mode

lcdcm0:        gosub wrlcd

       high lcdrs              ' back to character mode

rtn:   return



' Send character in lcdchr to the LCD. lcdchr preserved.

' Note that lcdrs, register select, is untouched.



wrlcd: outa = lcdchr >> 4      ' output high nibble

wrlcd1:        pulsout lcde,1

       outa = lcdchr           ' low nibble

       pulsout lcde,1

       return



' code shortening routines - we send a separator or command followed

' by a bcd character to the display a lot. the code also relies on the

' fact that wrlcd and wrbcd use different inputs and preserve them.



wrcb:  low lcdrs               ' select command mode



wrsb:  gosub wrlcd             ' do separator in lcdchr

       high lcdrs              ' fall through to do bcd



' send the BCD byte in bcd to the LCD as 2 characters

' bcd preserved



wrbcd: outa = 3                ' output lcdchr as 2 bcd chars

       pulsout lcde,1          ' hex 3x is a digit

       outa = bcd >> 4         ' digit info for high digit

       pulsout lcde,1

       outa = 3                ' now do the low digit

       pulsout lcde,1

       outa = bcd              ' low nibble

       pulsout lcde,1

       return



' end of the program



' More on the hardware portion:

' Power supplied through an LM2930 to220 5 volt regulator. Average

' current needed is around 5mA

' Rather than use the onboard regulator, the Stamp II is also run

' off the main 3 terminal regulator. Power for the DS1202 clock

' chip is provided through a 1N914 diode from the +5 line, and

' from a 3V lithium coin cell through another 1N914 to provide

' backup power for the clock.



' Pulldown resistors are present on the rst* and clk pins of the

' DS1202 clock chip- this precludes false clocking when the Stamp II

' I/O pins go high impedance for 18ms at the end of each nap.

' On the LCD, pins 3 and 5 of the LCD are tied low, so the LCD is

' treated as a write-only device. With some multi-line LCDs, pin 3

' may require a negative bias voltage. Even though the LCD is only 16

' characters wide, the second line at character 40.
Back to the Table of Contents

BS-2 Program 1:

From PIC@baker.pc.my    Sat Jun 29 07:28:04 1996

Date: Fri, 28 Jun 1996 18:57:42 +0000

From: David Baker 

Reply to: stamps@parallaxinc.com

To: stamps@parallaxinc.com

Subject: Re: [STAMPS] DS1202 & Stamp



On 28 Jun 96 at 3:08, WARPEDRIVE@aol.com wrote:



> Yes, excellent question.. anyone already written this interface code? I could

> really use the time savings about now..



I just had a quick go today - it turned out to be very easy. The 

program's pretty short so I guess people won't mind if I post it 

here. I haven't tidied it up yet & there may be a better way to do 

it, but here it is:



'------------------------------------------------------------------------

'       DS1202_C.BS2

'       Written by Dave Baker                                &nbsnbsp; 28JUN96



'       Sets the Dallas DS1202 real time clock chip to a preset time

'       & enables the clock to start counting.

'       Reading & writing of time done by burst programming method.



CEnable         con     $55     ' Clock Start

MinVal          con     $59     ' Preset value for minutes

HourVal         con     $23     ' Preset value for hours

DayVal          con     $31     ' Preset value for day

MonthVal        con     $12     ' Preset value for month

DCVal           con     $00     ' Preset value for dow - don't care

YearVal         con     $96     ' Preset value for year



RST             con     10      ' Reset pin 10

IO              con     9       ' IO pin 9

SCLK            con     8       ' Serial clock pin 8

pauseval        con     1       ' Value for pauses



WEnable         con     $00     ' Write enable

WSec            con     $80     ' Write to seconds register

Rsec            con     $81     ' Read seconds register

Wmin            con     $82     ' Write to minutes register

Rmin            con     $83     ' Read minutes register

Whour           con     $84     ' Write to hours register

Rhour           con     $85     ' Read hours register

Wday            con     $86     ' Write to days register

Rday            con     $87     ' Read day register

Wmonth          con     $88     ' Write to months register

Rmonth          con     $89     ' Read month register

Wyear           con     $8C     ' Write to years register

Ryear           con     $8D     ' Read year register

WCont           con     $8E     ' Write to control register

WCB             con     $BE     ' Read clock burst

RCB             con     $BF     ' Write clock burst



IOSec           var     word    ' store register data for seconds

IOMin           var     word    ' store register data for minutes

IOHour          var     word    ' store register data for hours

IODay           var     word    ' store register data for day

IOMonth         var     word    ' store register data for month

IODCare         var     word    ' For day of week - don't care

IOYear          var     word    ' store register data for year

Tmonth1         var     byte

Tmonth2         var     byte

Tmonth3         var     byte

IOMDec          var     word



                pause pauseval

                high RST

                ' tell 1202 that we want to write a clock burst 

                shiftout IO,SCLK,lsbfirst,[WCB]

                ' read everything in a burst

                Shiftout  

IO,SCLK,lsbfirst,[Cenable,MinVal,HourVal,DayVal,MonthVal,DCVal,YearVal,Wenable]

                low RST

loop:

                pause pauseval

                high RST

                ' tell 1202 that we want to read a clock burst 

                shiftout IO,SCLK,lsbfirst,[RCB]

                ' read everything in a burst

                Shiftin  

IO,SCLK,lsbpre,[IOSec\8,IOMin\8,IOhour\8,IOday\8,IOmonth\8,IODcare\8,IOyear\8]

                low RST

                gosub TextMonth

                gosub display

                goto loop

display:        

                debug HEX2 IOHour,":",Hex2 IOMin,":",Hex2 IOSec,"   "

                debug HEX2 IODay," "

                'debug HEX2 IOMonth, " "

                debug Tmonth1,Tmonth2,Tmonth3, " "

                debug HEX2 IOYear,cr

                'pause 100

                goto loop

TextMonth:

                ' convert month from BCD to decimal value

                IOMDec = (IOMonth.nib1 * 10) + (IOMonth.nib0)

                lookup IOMDec*3,["   

","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],TMonth1

                lookup IOMDec*3+1,["   

","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],TMonth2

                lookup IOMDec*3+2,["   

","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],TMonth3

                return

'------------------------------------------------------------------------



Looks like my wordwrap messed up a couple of the lines - the shiftin, 

shiftout & lookup lines aren't supposed to be wrapped.



That's a good start anyway. Don McKenzie has a similar program on his 

homepage from Bob Martin - I found it after I had already written 

mine. (Honest!) Actually mine uses the burst programming method which 

means a lot less code & is faster. Also even though Bob says shifting 

can only read 16 bits max I had no trouble reading in 8 bytes at a 

time.



Dave
Back to the Table of Contents

BS-2 Program 3:

From: "Craig Simmons" simmons@airmail.net

To: stamps@parallaxinc.com

Subject: [STAMPS] Re: JRC6355ED Real Time Clock Problem

Date: Sat, 14 Dec 1996 04:21:25 -0600



Well,



I answered my own question on this one, and since it threw me for a loop

I thought I would share it with you all. It seems that you have to enable

the chip, then disable it between read cycles or the counter will never get

incremented. Makes sense, guess I just need some sleep. I have included the

code that debugs the time to the screen for those that want to use the

chip. It really has a great price compared to the EPSON, but since I

haven't used the EPSON, I can't compare. I will say that I had a devil of a

time finding information on this chip. Scott Edwards notes in the Nuts and

Volts archive were a help for schematics, and some information I found on

the PicStic had the instruction set which was invaluable. I ranting again.

The code is below. Thanks again for this group and the massive serarch

engines on the internet.



Craig Simmons



' This code is for the BS2 to read and write the time to an NJU6355ED or

JRC6355ED real time clock



' Variables

TEMP            Var BYTE

ENABLE  CON 13

IO              CON 12

DATAPIN CON 14

CLOCKPIN        CON 15



' Put it into Write Mode and Set Time 

HIGH IO

HIGH ENABLE

shiftout DATAPIN,CLOCKPIN,0,[$96\8] ' Year (0-99)

shiftout DATAPIN,CLOCKPIN,0,[$12\8] ' Month (1-12)

shiftout DATAPIN,CLOCKPIN,0,[$13\8] ' Date (1-31)

shiftout DATAPIN,CLOCKPIN,0,[$06\4] ' Day of Week (1-7)

shiftout DATAPIN,CLOCKPIN,0,[$08\8] ' Hour (0-24)

shiftout DATAPIN,CLOCKPIN,0,[$54\8] ' Minute (0-60) 

Low ENABLE                               ' (Seconds reset automatically)     &nb  



' Put it into Read Mode

LOW IO 



' Loop to read in the time and display

GetTime:

        HIGH ENABLE ' You have to have this here. 

        shiftin DATAPIN,CLOCKPIN,1,[temp\8]

        debug hex(temp) ' Year

        shiftin DATAPIN,CLOCKPIN,1,[temp\8]

        debug hex(temp) ' Month

        shiftin DATAPIN,CLOCKPIN,1,[temp\8]

        debug hex(temp) ' Date

        shiftin DATAPIN,CLOCKPIN,1,[temp\4]

        debug hex(temp) ' Day of Week

        shiftin DATAPIN,CLOCKPIN,1,[temp\8]

        debug hex(temp) ' Hour

        shiftin DATAPIN,CLOCKPIN,1,[temp\8]

        debug hex(temp) ' Minute

        shiftin DATAPIN,CLOCKPIN,1,[temp\8]

        debug hex(temp) ' Seconds

        debug cr

        LOW ENABLE ' And you have to have this here.

        pause 1000

GOTO GetTime
Back to the Table of Contents

BS-2 Program 4:

From: "Dragan Kujovic" dkujovic@EUnet.yu

To: "Parallax Inc. Stamps" stamps@parallaxinc.com

Subject: [STAMPS] PCF8593P Real Time Clock

Date: Tue, 17 Dec 1996 14:23:52 +0100



Respectable Colleagues,



I am currently occupied with finishing couple of mine projects which all

have RTC implemented. But in Europe is very hard to find products from USA

manufacturers, such as Dallas, JRC etc.



So, I made RTC with Philips PCF8593P which can be found all over Europe.



There is example code for day, date & time clock with daylight savings.

Might be useful for implementing in some application.



PCF8593 data and application notes can be downloaded from:

http://www.semiconductors.philips.com/





Thanks to Jeff Martin for technical support,



and



thanks to Jordan Haralampopulos for I2C subroutines.





===============================================





'          ***************************************************

'            PHILIPS Real Time Clock PCF8593P (I2C protocol)

'          ***************************************************



'            Dragan Kujovic, EMAX Electronics, December 1996.





' USED PRODUCTS:

' Parallax Basic Stamp 2

' Parallax Serial LCD ( 2 x 16 characters)

' Philips real time clock PCF8593P





' Please be noticed that these products and source code for the RTC

' are not designed for use in life support appliances, devices,

' or systems where malfunction of these products can reasonably be expected

' to result in personal injury !





' This BS2 code read data from RTC and display it on Parallax serial LCD





' PCF8593 data and application notes can be downloaded from:

' www.semiconductors.philips.com





' BS2 pin description:

' RTC clock     =>      10

' RTC data      =>      11

' RTC reset     =>       0

' LCD Rx        =>       7





RTCaddress              VAR     WORD                    ' 16-bit address

RTCaddressHigh  VAR     RTCaddress.HIGHBYTE     '  8 MS-bit address

RTCaddressLow           VAR     RTCaddress.LOWBYTE      '  8 LS-bit address

RTCtemp         VAR     BYTE                    ' Temporary variable

RTCdata         VAR     BYTE                    ' Data variable

RTCack                  VAR     BIT                   &p; ' RTC acknowledge bit

RTCclockPin             CON     10                      ' RTC clock pi

RTCdataPin              CON     11                      ' RTC datin

RTCwrite                CON     %10100010               ' RTC Slave address write

RTCread         CON     %10100011               ' RTC Slave address read

ResetRTC                CON     %00000000               ' Status Byte Default

Second                  VAR     BYTE                   Second

Second1         VAR     BYTE                    ' 1 second

Second10                VAR     BYTE                    ' 10 seco

Minute                  VAR     BYTE                   Minute

Minute1                 VAR     BYTE                    ' 1 ute

Minute10                VAR     BYTE                    ' 10 minu

Hour                    VAR     BYTE                 &n;  ' Hour

Hour1                   VAR     BYTE                  &p; ' 1 hour

Hour10                  VAR     BYTE                   10 hours

Date                    VAR     BYTE                 &n;  ' Day

Date1                   VAR     BYTE                  &p; ' 1 day

Date10                  VAR     BYTE                   10 days

Day                     VAR     BYTE                &nb   ' Day

Month                   VAR     BYTE                  &p; ' Month

Month1                  VAR     BYTE                   1 month

Month10         VAR     BYTE                    ' 10 months

Year                    VAR     BYTE                 &n;  ' Year

Year1                   VAR     BYTE                  &p; ' 4 years

EEprom                  VAR     BYTE                   EEPROM data

N                       VAR     BYTE              &nbspbsp;    ' Universal counter



DATA "Sun","Mon","Tue","Wed","Thu","Fri","Sat"

DATA "Jan","Feb","Mar","Apr","May","Jun"

DATA "Jul","Aug","Sep","Oct","Nov","Dec"



' --------------------------------------------------------

' PCF8593 need reset only after connection to power supply



' PCF8593 hardware reset (Reset pin pull down)

' LOW 0:PAUSE 500:HIGH 0



' PCF8593 software reset (Reset all variables)

' FOR N=0 TO 15

' RTCaddressLow=N

' RTCtemp=ResetRTC

' GOSUB WriteToRTC

' NEXT

' --------------------------------------------------------





' -------------------------------------------------------------

' Set current time & date sample => Tue, 17. Dec 1996. 10:00:00



' For details consult PCF8593 file which can be downloaded from

' www.semiconductors.philips.com



' RTCaddressLow=5:      ' Year, Date

' RTCtemp=%00010111:    ' 1996 / 17

' GOSUB WriteToRTC

' RTCaddressLow=6:      ' Month, Day

' RTCtemp=%01010010:    ' 12 / Tue

' GOSUB WriteToRTC

' RTCaddressLow=4:      ' Hour

' RTCtemp=%00010000:    ' 10 

' GOSUB WriteToRTC

' RTCaddressLow=3:      ' Minute

' RTCtemp=%00000000:    ' 0

' GOSUB WriteToRTC

' -------------------------------------------------------------





SEROUT 7,396,[12,"                                "]    ' LCD reset

FREQOUT 14,100,3000     ' Make a "beep"



RTC:



' Day

RTCaddressLow=6

RTCtemp=0

GOSUB ReadFromRTC

IF RTCtemp.BIT7=%0 AND RTCtemp.BIT6=%0 AND RTCtemp.BIT5=%0 THEN D0

IF RTCtemp.BIT7=%0 AND RTCtemp.BIT6=%0 AND RTCtemp.BIT5=%1 THEN D1

IF RTCtemp.BIT7=%0 AND RTCtemp.BIT6=%1 AND RTCtemp.BIT5=%0 THEN D2

IF RTCtemp.BIT7=%0 AND RTCtemp.BIT6=%1 AND RTCtemp.BIT5=%1 THEN D3

IF RTCtemp.BIT7=%1 AND RTCtemp.BIT6=%0 AND RTCtemp.BIT5=%0 THEN D4

IF RTCtemp.BIT7=%1 AND RTCtemp.BIT6=%0 AND RTCtemp.BIT5=%1 THEN D5

IF RTCtemp.BIT7=%1 AND RTCtemp.BIT6=%1 AND RTCtemp.BIT5=%0 THEN D6

Days:



' Date

RTCaddressLow=5

RTCtemp=0:Date=0:Date1=0:Date10=0

GOSUB ReadFromRTC

IF RTCtemp.BIT5=%1 AND RTCtemp.BIT4=%1 THEN D30

IF RTCtemp.BIT5=%1 AND RTCtemp.BIT4=%0 THEN D20

IF RTCtemp.BIT5=%0 AND RTCtemp.BIT4=%1 THEN D10

Dates:

Date1=RTCtemp.LOWNIB

Date=Date10+Date1



' Month

RTCaddressLow=6

RTCtemp=0:Month=0:Month1=0:Month10=0

GOSUB ReadFromRTC

IF RTCtemp.BIT4=%1 THEN M10

Months:

Month1=RTCtemp.LOWNIB

Month=Month10+Month1



' Year

RTCaddressLow=5

RTCtemp=0:Year=0:Year1=0

GOSUB ReadFromRTC



IF RTCtemp.BIT7=%1 AND RTCtemp.BIT6=%1 THEN Y3

IF RTCtemp.BIT7=%1 AND RTCtemp.BIT6=%0 THEN Y2

IF RTCtemp.BIT7=%0 AND RTCtemp.BIT6=%1 THEN Y1

Years:

Year=Year1+96



' Hour

RTCaddressLow=4

RTCtemp=0:Hour=0:Hour1=0:Hour10=0

GOSUB ReadFromRTC

IF RTCtemp.BIT5=%1 THEN H20

IF RTCtemp.BIT4=%1 THEN H10

Hours:

Hour1=RTCtemp.LOWNIB

Hour=Hour10+Hour1



' Minute

RTCaddressLow=3

RTCtemp=0:Minute=0:Minute1=0:Minute10=0

GOSUB ReadFromRTC

Minutes:

Minute10=RTCtemp.HIGHNIB*10

Minute1=RTCtemp.LOWNIB

Minute=Minute10+Minute1



' Second

RTCaddressLow=2

RTCtemp=0:Second=0:Second1=0:Second10=0

GOSUB ReadFromRTC

Seconds:

Second10=RTCtemp.HIGHNIB*10

Second1=RTCtemp.LOWNIB

Second=Second10+Second1



' Daylight savings time

' Last Saturday/Sunday weekend in April and October at 2 AM

READ $03E,EEprom

IF Hour=2 AND Day=0 AND Month=4 AND Date>24 AND EEprom=0 THEN AddHour

READ $03F,EEprom

IF Hour=2 AND Day=0 AND Month=10 AND Date>24 AND EEProm=0 THEN SubtractHour



FOR N=0 TO 2

READ Day*3+N,EEprom

SEROUT 7,396,[27,N,EEprom]

NEXT



SEROUT 7,396,[27,3,", ",dec Date]

SEROUT 7,396,[27,7,"."]



FOR N=0 TO 2

READ Month+6*3+N,EEprom

SEROUT 7,396,[27,N+9,EEprom]

NEXT



SEROUT 7,396,[27,13,dec Year,"."]



SEROUT 7,396,[27,20,dec Hour]

SEROUT 7,396,[27,22,":"]

SEROUT 7,396,[27,23,dec Minute]

SEROUT 7,396,[27,25,":"]

SEROUT 7,396,[27,26,dec Second,"     "]



GOTO RTC



D0:Day=0:GOTO Days

D1:Day=1:GOTO Days

D2:Day=2:GOTO Days

D3:Day=3:GOTO Days

D4:Day=4:GOTO Days

D5:Day=5:GOTO Days

D6:Day=6:GOTO Days



D10:Date10=10:GOTO Dates

D20:Date10=20:GOTO Dates

D30:Date10=30:GOTO Dates



M10:Month10=10:GOTO Months



Y1:Year1=1:GOTO Years

Y2:Year1=2:GOTO Years

Y3:Year1=3:GOTO Years



H10:Hour10=10:GOTO Hours

H20:Hour10=20:GOTO Hours



AddHour:

RTCaddressLow=4

RTCtemp=%00000011:      ' Set Hour to 3 AM

GOSUB WriteToRTC

WRITE $03E,1

WRITE $03F,0

GOTO RTC



SubtractHour:

RTCaddressLow=4

RTCtemp=%00000001:      ' Set Hour to 1 AM

GOSUB WriteToRTC

WRITE $03F,1

WRITE $03E,0

GOTO RTC



' *************************************************************************



' Basic Stamp II / I2C SUBROUTINES



WriteToRTC:

GOSUB StartRTC:         ' Send START sequence to RTC

RTCdata=RTCwrite:               ' Slave address with WRITE command

GOSUB TxByte:           ' Send slave address with WRITE command to RTC 

GOSUB RxACK:            ' Receive ACK signal from RTC

RTCdata=RTCaddressLow:  ' RTC writting address determination

GOSUB TxByte:           ' Send writting address to RTC 

GOSUB RxACK:            ' Receive ACK signal from RTC

RTCdata=RTCtemp:                ' Write data from temporary variable

GOSUB TxByte:           ' Send byte to determinated address in RTC 

GOSUB RxACK:            ' Receive ACK signal from RTC

GOSUB StopRTC:          ' Send STOP sequence to RTC

RETURN



ReadFromRTC:

GOSUB StartRTC:         ' Send START sequence to RTC

RTCdata=RTCwrite:               ' Slave address with WRITE command

GOSUB TxByte:           ' Send slave address with WRITE command to RTC 

GOSUB RxACK:            ' Receive ACK signal from RTC

RTCdata=RTCaddressLow:  ' RTC writting address determination

GOSUB TxByte:           ' Send writting address to RTC 

GOSUB RxACK:            ' Receive ACK signal from RTC

GOSUB StartRTC:         ' Send again START sequence to RTC

RTCdata=RTCread:                ' Slave address with READ command

GOSUB TxByte:           ' Send slave address with READ command to RTC 

GOSUB RxACK:            ' Receive ACK signal from RTC

GOSUB RxByte:           ' Read data from RTC-a

RTCtemp=RTCdata:                ' Place data from RTC in RTCtemp variable

GOSUB StopRTC:          ' Send STOP sequence to RTC

RETURN 



StartRTC:

HIGH RTCdataPin:                ' RTC data pin high

HIGH RTCclockPin:               ' RTC clock pin high

LOW RTCdataPin:         ' RTC data pin low

RETURN



StopRTC:

LOW RTCdataPin:         ' RTC data pin low

HIGH RTCclockPin:               ' RTC clock pin high

HIGH RTCdataPin:                ' RTC data pin high

RETURN



TxByte:

SHIFTOUT RTCdataPin,RTCclockPin,1,[RTCdata]     ' Send byte to RTC

RETURN



RxByte:

SHIFTIN RTCdataPin,RTCclockPin,0,[RTCdata]      ' Receive byte from RTC

RETURN



TxACK:

SHIFTOUT RTCdataPin,RTCclockPin,1,[%0\1]        ' Send ACK bit to RTC

RETURN



RxACK:

SHIFTIN RTCdataPin,RTCclockPin,0,[RTCack\1]     ' Receive ACK bit from RTC

RETURN



' *************************************************************************



END



===============================================





With best regards,



Dipl. Ing. Dragan Kujovic



EMAX Electronics

Tel. ++381 11 185-188

Fax ++381 11 185-199



E-mail: dkujovic@EUnet.yu
Back to the Table of Contents

FED Basic:

; This program is for the 16c57 FED Basic

; it drives a 16x2 LCD display on port B and DS1302 on port C

;

; On 1st power-up the CH (clock hold) flag will be set and will

; have to be reset before the clock can count enter your initial time

; below in inithr & initmin variables.

;

; To reset clock after being set the first time just remove power

; and one of the backup batteries connected to VCC1 of the DS1302

;

; RTC chip is wired as follows:

;

; c5=RST, c6=SCLK, c7=I/O

;

; Mick Gulovsen 20-Apr-96  bigmik@blaze.net.au



typesub gettime()               ; get time

typesub disptime()              ; display time

typesub selreg(data)            ; select register

typesub clkwr(data)             ; clock data into RTC

typesub clkwr1(data)            ;         "

typesub initclk()

typefunc clkrd()                ; clock data out of RTC



temp=0

hr=0

hrx=0

min=0

minx=0

sec=0

secx=0

reg=0

data=0



begin:



; initial start time here

;

; format as follows

;

; 0xxx yyyy    where

;

;xxx=tens of hrs/mins and yyyy=units of hrs/mins



inithr=100001n                  ; 21:xx

initmin=0110000n                ; xx:30



trisc(0)                        ; set clock I/O to outputs

portc = 0                       ; clock I/O Low



;initclk()              ; ################ temp always init clock

;goto initlcd:



;************* check if clock running *****************

;

; If seconds reg doesnt change after 1.1 seconds then initialise

; clock using the inithr & initmin variables above.



gettime()

temp=sec

wait(1100)

gettime()

if sec=temp then initclk()



initlcd:



lcd(-2)                         ; 2 line

lcd(257)                        ; clear and home



lcdstring("Clock MBG APR-96")



main:



gettime()

disptime()



goto main:              ; restart whole cycle

;*************** select Register *******************

sub selreg(data)



trisc(0)



c6 = 0                          ; set sclk LOW  

c5 = 1                          ; set RST high



clkwr1(data)

return

end

;*************** Clock Write *******************

sub clkwr(data)



clkwr1(data)

c5 = 0                          ; set RST Low

return

end

;************* output data to RTC *************

sub clkwr1(data)        

                        

c7 = data & 1                   ; 

clocks(1,ADDPORTC+96)           ; clock in bit0

c7 = data>>1 & 1                ; 

clocks(1,ADDPORTC+96)           ; clock in bit1

c7 = data>>2 & 1                ; 

clocks(1,ADDPORTC+96)           ; clock in bit2

c7 = data>>3 & 1                ; 

clocks(1,ADDPORTC+96)           ; clock in bit3

c7 = data>>4 & 1                ; 

clocks(1,ADDPORTC+96)           ; clock in bit4

c7 = data>>5 & 1                ; 

clocks(1,ADDPORTC+96)           ; clock in bit5

c7 = data>>6 & 1                ; 

clocks(1,ADDPORTC+96)           ; clock in bit6

c7 = data>>7 & 1                ; 

clocks(1,ADDPORTC+96)           ; clock in bit7

return

end

;************** read in data from RTC ***********

func clkrd()



trisc(10000000n)                ; set I/O for INPUT (c7)



;clocks(1,ADDPORTC+96)          ; clock out bit0

                                ; NOTE! This is not needed as the

                                ; act of clocking in the last bit

                                ; of the register select routine

                                ; actually clocks out the 1st bit

                                ; of a following read routine

                                ; because writes are clocked in on

                                ; rising edges of SCLK whereas reads

                                ; are clocked out on falling edges.

if c7=-1 then data=1 

if c7=0 then data=0



clocks(1,ADDPORTC+96)           ; clock out bit1

if c7=-1 then data=data+2

clocks(1,ADDPORTC+96)           ; clock out bit2

if c7=-1 then data=data+4

clocks(1,ADDPORTC+96)           ; clock out bit3

if c7=-1 then data=data+8

clocks(1,ADDPORTC+96)           ; clock out bit4

if c7=-1 then data=data+16 

clocks(1,ADDPORTC+96)           ; clock out bit5

if c7=-1 then data=data+32

clocks(1,ADDPORTC+96)           ; clock out bit6

if c7=-1 then data=data+64

clocks(1,ADDPORTC+96)           ; clock out bit7

if c7=-1 then data=data+64+64



c5 = 0                          ; set RST Low

return  data

end

;*************** get time *********************

sub gettime()



selreg(10000101n)               ; hour reg. (RD)

clkrd()                         ; read reg

hr=data&15

hrx=(data>>4)&3



selreg(10000011n)               ; minutes reg. (RD)

clkrd()                         ; read reg

min=data&15

minx=(data>>4)&7



selreg(10000001n)               ; seconds reg. (RD)

clkrd()                         ; read reg

sec=data&15

secx=(data>>4)&7

return

end

;*********** display time **********

sub disptime()



lcd(256+192+0)                  ; position for time display

lcd(hrx+48)

lcd(hr+48)

lcd(':')

lcd(minx+48)

lcd(min+48)

lcd(':')

lcd(secx+48)

lcd(sec+48)

return

end

;************* init clock *********************

sub initclk()



selreg(10001110n)               ; Control reg. (WR)

clkwr(0)                        ; Reset WP flag



selreg(10000100n)               ; Hours reg. (WR)

clkwr(inithr)



selreg(10000010n)               ; Mins reg. (WR)

clkwr(initmin)



selreg(10010000n)               ; Trickle Charge reg (WR)

clkwr(10100101n)                ; 1 diode, 2k resistor (2ma charge)



selreg(10000000n)               ; secs reg. +CH (bit7) (WR)

clkwr(2)                        ; +2 secs for initialise delays



return

end
Back to Top of Page

PIC MicroChip Code by Mark Sullivan

Date:         Thu, 25 Jul 1996

From: Mark K Sullivan 

Subject:      Re: Real Time Clocks (implementing)

To: Multiple recipients of list PICLIST 



I've used Dallas DS1202 with the 16C54.  It works well.  I powered it from a

.22F double layer capacitor when the power is off and it will keep the time for

a couple of weeks.



I wouldn't think 16C74 software code (using an interrupt timer) would be much

bigger than what I used to talk to the DS1202.  I used the 1202 because 1> it

made the 16C54 code easier (no interrupts y'know) and 2> it made the capacitor

backup much easier in my application.



Code follows.  This ran on an 8 MHz ceramic resonator.  Sorry about the

documentation (what documentation?!).  I didn't know I was going to share it.

The times are stored in BCD, just like in the DS1202 documentation.



        ;

        PROCESSOR       PIC16C54

        RADIX   DEC

        ;

#include "16c54.inc"

        ;

        cblock  8

        Timer1

        Timer2

        Timer3

        Count

        Second

        Minute

        Hour

        Date

        Month

        Day

        Year

        endc

        ;

; PB4 - CLOCK to calendar clock

#define SCLK portb,4

; PA2 - I/O to calendar clock.

#define CLKDATA porta,2

; PA3 - RST to calendar clock.

#define CLKRST porta,3

        ;

        org     0

        ;

RESET   movlw   00h

        movwf   porta   ;turn off outputs

        movwf   portb

        movlw   00h

        tris    portb   ;all outputs

        movlw   03h

        tris    porta   ;PA0,1 are inputs

        ;

;

; Set time

;

        call    RClock

        ;

        movlw   96h

        movwf   Year

        movlw   08h

        movwf   Date

        movlw   02h

        movwf   Day

        movlw   04h

        movwf   Month

        movlw   17h

        movwf   Hour

        movlw   25h

        movwf   Minute

        movlw   00h

        movwf   Second

        call    WClock



;all done

stop    goto    stop



        ;

;

; Write calendar clock

;

WClock  bcf     SCLK    ;negate clock

        nop

        nop

        nop

        nop

        bcf     CLKDATA

        bsf     CLKRST  ;negate RST

        movlw   03h

        tris    porta   ;I/O is output

        movlw   08eh    ;write control register

        call    wbyte

        movlw   00h     ;turn off WP

        call    wbyte

        movlw   7

        movwf   Timer3

        movlw   80h

        movwf   Count

        movlw   Second

        movwf   fsr

wc      bcf     CLKRST  ;assert RST

        bcf     SCLK    ;negate clock

        nop

        nop

        nop

        nop

        bsf     CLKRST  ;negate RST

        movf    Count,W

        call    wbyte

        movf    indf,W

        call    wbyte

        incf    fsr

        incf    Count

        incf    Count

        decfsz  Timer3

        goto    wc

        bcf     CLKRST  ;assert RST

        retlw   0

        ;

;

; Read calendar clock

;

RClock  bcf     SCLK    ;negate clock

        nop

        nop

        nop

        nop

        bcf     CLKDATA ;negate I/O

        bsf     CLKRST  ;negate RST

        movlw   03h

        tris    porta   ;I/O is output

        movlw   0bfh    ;burst read clock registers

        call    wbyte

        movlw   07h

        tris    porta   ;I/O is input

        movlw   Second

        movwf   fsr

        call    rbyte

        call    rbyte

        call    rbyte

        call    rbyte

        call    rbyte

        call    rbyte

        call    rbyte

        bcf     CLKRST  ;assert RST

        retlw   0

        ;

wbyte   movwf   Timer2

        movlw   8

        movwf   Timer1

wbit    bcf     SCLK

        btfss   Timer2,0

        bcf     CLKDATA

        btfsc   Timer2,0

        bsf     CLKDATA

        nop

        nop                     ;data to clock setup

        nop

        bsf     SCLK

        rrf     Timer2

        decfsz  Timer1

        goto    wbit

        retlw   0

        ;

rbyte   movlw   8

        movwf   Timer1

rbit    bcf     SCLK

        nop

        nop                     ;clock to data delay

        rrf     indf

        bcf     indf,7

        btfsc   CLKDATA

        bsf     indf,7

        bsf     SCLK

        nop

        nop

        decfsz  Timer1

        goto    rbit

        incf    fsr

        retlw   0

        ;

        org     1ffh

        goto    RESET

        ;

        end
Back to the Table of Contents

DS-1202 problems by Llewellyn Griffiths

From: Llewellyn Griffiths llga@acslink.aone.net.au

Newsgroups: aus.electronics,comp.realtime,comp.arch.embedded

Subject: Re: DS 1202 Problem

Date: Mon, 13 Jan 1997 19:13:25 +1000



Regarding DS-1202 Problems



Some time ago I posted an article regarding problems setting the time

and date in a DS-1202 just as it rolled over at midnight. Since nobody

responded, I can only assume that this is a problem that is  rarely

encountered. In the meantime I have received confirmation from Dallas

that this condition can occur if the RTC is updated when the chip's

internal state machine is rolling over the date and time. 



It can be easily circumvented by waiting until the midnight rollover has

finished before setting the date and time.



While this situation obviously does not arise very often, I have posted

this article so that anybody who does come across it will not have to

waste time trying to determine the cause.
Back to the Table of Contents

PIC MicroChip Code by John Sanderson

23 August 1998. Johannesburg

John Sanderson, JS Controls. jsand@pixie.co.za



notes:-

This code was written for a small daughter board, hosting a 16F84, to be

built into an existing instrument design.

It has a Real Time clock chip [DS1302], that comms. with the F84 by its

3-wire i/f. 



There is BCD information read in from a mc14433 adc incorporated

in a DPM reading engineering units.

RS232 serial information is blasted out to a local printer, detailing the

time, DPM reading in 3 1/2 digit format, and a serial number incremented

in F84 EEPROM in three binary locations.

The data could just as easily go to a local PC com:port



Lastly, there are a couple of push switches and inputs from reed relays

here too, to initiate data dumping.

Lots of massage is needed to get the data into the right formats for all 

this, this can be seen in the subroutinery.



Goodly chunks of the code have been cribbed from other folk's past PIClist

contributions, and from other places too I'm sure. 

Having this stuff archived away saved me probably 50% of the time needed 

to get this app. finished.

I've kept the names of the earlier contributors in the source code here

as a form of recognition. 

My most heartfelt thanks go out to them.



;/////////////////////////////////////////////////////////////////////////

;////                           rtc1302.ASM             &nbsnbsp;            ////

;////                                         &nbsnbsp;                      ////

;////   This module carries a Dallas DS1302 real time clock part.

;       There is NO Xtal or Battery in this part, the time is held in

;       registers for year, month, day hour etc.

;       communication with the ds1302 is by 3-wire interface /rst,clk,dataq



;////   It reads / communicates with a FEMA MAG-35 panel DVM

;////   This uses a Motorola mc14433 adc, which can have the e.o.c. / d.u.

;////   lines disconnected.

;

;

;       Functions:-

;       1. To HOLD DRO display on command of `closed relay' contacts from

;       the rr4 contacts on the m/board.

;       2. To send serial output after the HOLD command.

;       specs

;       baud rate       parity  data bits       stop bits               

;       2400            n       8               2

;       data

;       year    month   day     hour    minute second   index   break value

;       yyyy    mm      dd      hh      mm      ss      iiiiii  kkkk

;

;       Pushbuttons on unit - or flying umbilical

;       1.      to advance time, faster as longer held in

;       2.      to retard       

;

;////   16c84 has 32 fregs.    16f84 has 68 fregs.                              sp;                                       //





;////   pin descriptions, DS 1302:-                                   sp; 

;////   16f84   pin     In/Out  function        **FOR PROTO-PIC ONLY!**

;////   ra0     17      I       reed rla 4 closure for HOLD

;////   ra1     18      O       rtc     /rst    pin5

;////   ra2     1       O       rtc     clk     pin7

;////   ra3     2       I/O     rtc     dq data pin6

;////   ra4     3       O       serial out rs232 0-5vdc (or up to 14v)

;////

;////   rb0     6       I/O     interrupt of D.U. of mc14433 adc

;////   rb1     7       I       BCD data from mc14433   Q0      pin20

;////   rb2     8       I       BCD                     Q1 &p;    pin21

;////   rb3     9       I       BCD                     Q2 &p;    pin22

;////   rb4     10      I       BCD most sig.           Q3      pin23

;////   rb5     11      I       normally HI switches    advance time

;////   rb6     12      I               "       "       retard time

;////   rb7     13      spare

;////                                         &nbsnbsp;                

;//////////////////////////////////////////////////////////////////////////



;******************************************assembler directives begin

                list    p=pic16f84

;               list    f=inhx8m

                list    r=dec           ;radix decimal, keeps operands happy

                __config _PWRTE_ON &_XT_OSC &_WDT_OFF

                errorlevel      1,-302  ;kill off page rp0 warnings

                

#include        

;******************************************assembler directives end



;******************************************system definitions

;FOR PROTO-PIC VERSION ONLY!



eerd            equ     0               ;eeprom eecon1,0 read bit

eewr            equ     1               ;eeprom eecon1,1 write bit



;porta

rr4             equ     0               ;reed relay4 closure.   LO=closed

_rst            equ     1               ;rtc reset line         LO=res

clk             equ     2               ;rtc clock (=sclk)

dataq           equ     3               ;rtc dq data line (=I/O)

tx              equ     4               ;rs232 tx line

#define         REED4   porta,rr4       ;INPUT ex m/b reed relay4. close=LO

#define         CLKRST  porta,_rst      ;RTC reset line LO=reset HI=active

#define         SCLK    porta,clk       ;RTC clock line 

#define         CLKDATA porta,dataq     ;RTC I/O data line

#define         SERTX   porta,tx        ;rs232 serial transmit line



;portb

eoc             equ     0               ;du = end of conv. int. and HOLD

bcd_q0          equ     1               ;bcd data. ls bit

bcd_q1          equ     2               ;bcd

bcd_q2          equ     3               ;bcd

bcd_q3          equ     4               ;bcd data. ms bit

up_switch       equ     5               ;normally HI switch for up time

down_switch     equ     6               ;"      "       " retard time

;               equ     7               ;spare

#define         EOC     portb,eoc

#define         BCD_Q0  portb,bcd_q0

#define         BCD_Q1  portb,bcd_q1

#define         BCD_Q2  portb,bcd_q2

#define         BCD_Q3  portb,bcd_q3

#define         UP_SWIT portb,up_switch

#define         DO_SWIT portb,down_switch

;#define                portb,



;general purpose bit definitions

;gpflags register

reed            equ     0               ;reed relay  `got pushed' flag

up              equ     1               ;up button `already pushed' flag

down            equ     2               ;down button `already pushed'



;general purpose register definitions

        cblock  0x0C

                m_porta                 ;mirror of port a

                m_portb                 ;mirror of port b

                gpflags                 ;general flags

                scratch                 ;scratch reg for *temporary* use

                scratch1                ;       "    &n;          



                count1                  ;counts 1,2,3 are for gen purpose

                count2                  ;delay routines

                count3                  ;

                up_count                ;count of 0.1 secs when UP switch closed

                down_count              ;count of 0.1 secs when DOWN switch closed



                timer1                  ;for 8bit rotates in/out

                timer2                  ;per Mark Sullivan's code 25.7.96

                timer3                  ;for the ds1202 or ds1302

                count4                  ;real-time-clock

                second                  ;

                minute                  ;

                hour                    ;

                date                    ;

                month                   ;

                day                     ;

                year                    ;

                

                ds1                     ;adc most sig. bcd byte-low nibble only

                ds2                     ; these are the bcd bytes as read in fro

                ds3                     ; the adc, and have been massaged into

                ds4                     ; (not packed) bcd



                tx_buff                 ;rs232 send routine

                pr01                    ;rs232 buffer table pointer offset

                

                samp_index1             ;sample index no. binary l.s.byte EEPROM

                samp_index2             ;binary eeprom

                samp_index3             ;binary most sig. index eeprom byte



                count5                  ;used in binary-to-bcd routine

                temp_f                  ;for outputting binary-held data to 

                buff_4                  ;bcd. bcd-to-ascii and rs232

                buff_3                  ;is then possible

                buff_2

                buff_1

                temp_a

                temp_b

                temp_c

                temp_d

                temp_e



        endc

;*********************************************end system definitions



;*********************************************system origin

                org     0x000

                goto    start

                org     0x004

                goto    service

;*********************************************end system origin



;************************************************tables first 

powerup_table1

                addwf   pcl,same

                retlw   0x59            ;Y      ASCII char

                retlw   0x65            ;e

                retlw   0x61            ;a

                retlw   0x72            ;r

                retlw   0x20            ;       sp

                retlw   0x4D            ;M

                retlw   0x6F            ;o

                retlw   0x20            ;       sp

                retlw   0x44            ;D

                retlw   0x61            ;a

                retlw   0x20            ;       sp

                retlw   0x20            ;       sp

                retlw   0x68            ;h

                retlw   0x72            ;r

                retlw   0x20            ;       sp

                retlw   0x6D            ;m

                retlw   0x69            ;i

                retlw   0x20            ;       sp

                retlw   0x73            ;s

                retlw   0x65            ;e

                retlw   0x20            ;       sp

                retlw   0x20            ;       sp

                retlw   0x69            ;i

                retlw   0x6E            ;n

                retlw   0x64            ;d

                retlw   0x65            ;e

                retlw   0x78            ;x

                retlw   0x20            ;       sp

                retlw   0x20            ;       sp

                retlw   0x20            ;       sp

                retlw   0x46            ;F

                retlw   0x6F            ;o

                retlw   0x72            ;r

                retlw   0x63            ;c

                retlw   0x65            ;e

                retlw   0x20            ;       sp

                retlw   0x20            ;       sp

                retlw   0x20            ;       sp

                retlw   0x20            ;       sp      

                retlw   0x20            ;       sp      40thar

                retlw   0x20            ;       sp      extrfor surety

                retlw   0x20            ;       sp

                retlw   0x20            ;       sp      extrfor surety

                retlw   0x20            ;       sp

;********************************************************end of tables



;*********************************************************initialisations

start

        ;clear all ram registers

                movlw   0x0C            ;start of ram

                movwf   fsr

                clrf    indf            ;$-3 to here

                incf    fsr,same

                btfss   fsr,7

                goto    $-3             ;back to clrf indf       &nbspbsp;                             

                bsf     status,rp0

        ;setup trisa, b

                movlw   00001001b

                movwf   trisa                       &nb   

                movlw   01111111b

                movwf   trisb

                bcf     status,rp0

                movlw   00000000b

                movwf   porta

                movwf   portb



;***************************************************end of initialisation



;*********************************************main loop begins

main_loop                       ;initial stuff

                call    delay_100ms

                call    rclock          ;fetch the current contents of rtc itself

                bcf     second,7        ;clear `clock halt' CH bit

                bcf     hour,7          ;am/pm:24 -> 24 hr mode

                call    wclock

                call    delay_1sec

                call    rclock

                movlw   0x12            ;ascii byte `DC2' resets compressed printing

                call    txbyte

                call    powerup_dump



main_loop1

        ;*********************** check the time advance &  retard switches

                call    rclock

                btfsc   UP_SWIT         ;switch is in, if result=LO

                goto    time_retard0    ;switch open, so drop thru & check DOWN

                btfsc   UP_SWIT

                goto    time_adv1

                call    inc_minute_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

time_adv1       btfsc   UP_SWIT

                goto    time_adv2

                call    inc_hour_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

time_adv2       btfsc   UP_SWIT

                goto    time_adv3

                call    inc_date_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

time_adv3       btfsc   UP_SWIT

                goto    time_adv4

                call    inc_month_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

time_adv4       btfsc   UP_SWIT

                goto    main_loop3

                call    inc_year_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

                goto    main_loop3



time_retard0    

                btfsc   DO_SWIT

                goto    main_loop3              ;jump out, no switch is in

                call    dec_minute_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

time_retard1    btfsc   DO_SWIT

                goto    time_retard2

                call    dec_hour_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

time_retard2    btfsc   DO_SWIT

                goto    time_retard3

                call    dec_date_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

time_retard3    btfsc   DO_SWIT

                goto    time_retard4

                call    dec_month_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

time_retard4    btfsc   DO_SWIT

                goto    main_loop3

                call    dec_year_bcd

                call    wclock

                call    crush_dump

                call    delay_1sec

        ;*********************** finish time advance &  retard

main_loop3      

                nop

                nop

                btfsc   REED4           ;test reed relay closure. LO=closed

                goto    main_loop4      ;open ie no TRIP



                btfss   gpflags,reed

                goto    main_loop6

                goto    main_loop1      

main_loop4      bcf     gpflags,reed

                bsf     status,rp0      ;set to bank1

                bsf     trisb,eoc       ;eoc becomes input

                bcf     status,rp0      ;set to bank0

                goto    main_loop1                     &nbspbsp;       

main_loop6      bsf     gpflags,reed

                call    inc_eeprom      ;increment eeprom regs+1

                call    read_adc        ;capture current force reading

                call    crush_dump      ;print one data dump only

                goto    main_loop1



;*********************************************main loop ends



;************************************** specific RTC ds1302 subroutines begin



;

; Write calendar clock

; per Mark K Sullivan 25.7.96

;       this routine takes ALL the seconds ---> year fregs in 16f84 and

;       writes them to the ds1302. NB that means that if you want to adjust

;       the rtc time registers, you have to do a read first (of them all).

;       The rclock routine following, reads the whole lot in `burst mode'

;       and puts the values into seconds --->year fregs



wclock  bcf     SCLK            ;negate clock line

        nop

        nop

        nop

        nop

        bcf     CLKDATA

        bsf     CLKRST          ;negate RST

        bsf     status,rp0      ;I/O dataq line set to output

        bcf     trisa,dataq

        bcf     status,rp0

        movlw   0x8E            ;write control register

        call    wbyte

        movlw   0x00            ;turn off Write Protect in rtc

        call    wbyte

        movlw   7

        movwf   timer3

        movlw   0x80            ;rtc register address for `second'

        movwf   count4

        movlw   second

        movwf   fsr

wc      bcf     CLKRST          ;assert RST

        bcf     SCLK            ;negate clock

        nop

        nop

        nop

        nop

        bsf     CLKRST          ;negate RST

        movf    count4,W

        call    wbyte

        movf    indf,W

        call    wbyte

        incf    fsr

        incf    count4

        incf    count4

        decfsz  timer3

        goto    wc

        bcf     CLKRST          ;assert RST

        return



;

; Read calendar clock

;





rclock  bcf     SCLK            ;negate clock

        nop

        nop

        nop

        nop

        bcf     CLKDATA         ;negate I/O

        bsf     CLKRST          ;negate RST

        bsf     status,rp0      ;I/O dataq line set to output

        bcf     trisa,dataq

        bcf     status,rp0

        movlw   0xBF            ;burst read clock registers

        call    wbyte

        bsf     status,rp0      ;I/O dataq line set to input

        bsf     trisa,dataq

        bcf     status,rp0

        movlw   second

        movwf   fsr

        call    rbyte

        call    rbyte

        call    rbyte

        call    rbyte

        call    rbyte

        call    rbyte

        call    rbyte

        bcf     CLKRST          ;assert RST

        return



wbyte   movwf   timer2

        movlw   8

        movwf   timer1

wbit    bcf     SCLK

        btfss   timer2,0

        bcf     CLKDATA

        btfsc   timer2,0

        bsf     CLKDATA

        nop

        nop                     ;data to clock setup

        nop

        bsf     SCLK

        rrf     timer2

        decfsz  timer1

        goto    wbit

        return



rbyte   movlw   8

        movwf   timer1

rbit    bcf     SCLK

        nop

        nop                     ;clock to data delay

        rrf     indf

        bcf     indf,7

        btfsc   CLKDATA

        bsf     indf,7

        bsf     SCLK

        nop

        nop

        decfsz  timer1

        goto    rbit

        incf    fsr

        return

;********************************************specific rtc ds1302 routines end



;********************************************specific adc mc14433 routines start

read_adc        ;capture adc data, bcd digits ds1..ds4

                        bsf     status,rp0

                        bsf     trisb,eoc       ;ensure eoc is an INPUT

                        bcf     status,rp0             sp;                                

read_adc1               btfss   EOC

                        goto    read_adc1       ;loop till eoc HI



                bsf     status,rp0      ;closed ie end-of-test TRIP condition

                bcf     trisb,eoc       ;make eoc an output

                bcf     status,rp0

                bcf     EOC             ;and pull it LO, ie freeze dro



                        call    delay_200us     ;read ds1 only in middle

                        call    delay_200us     ;read ds1 only in middle

                        call    delay_200us     ;read ds1 only in middle

                        movf    portb,w

                        movwf   ds1             ;most sig. digit sp;                      

                        call    delay_200us     ;read in middle of valid

                        call    delay_200us

                        movf    portb,w

                        movwf   ds2             ;next sig. digit sp;                      

                        call    delay_200us     ;read in middle of valid

                        call    delay_200us     ;read in middle of valid

                        call    delay_200us

                        movf    portb,w

                        movwf   ds3             ;next sig. digit sp;                      

                        call    delay_200us     ;read in middle of valid

                        call    delay_200us

                        call    delay_200us     ;read in middle of valid

                        movf    portb,w

                        movwf   ds4             ;least sig. digit&nbspbsp;                     

                ;now massage each of these

                        btfss   ds1,4           ;check the Q3 bit as `raw'

                        goto    $+4             ;ms digit only reres

                        movlw   0x30            ; ascii 0 

                        movwf   ds1

                        goto    $+3

                        movlw   0x31            ; or ascii 1

                        movwf   ds1

                        movlw   00001111b

                        rrf     ds2,same

                        andwf   ds2,same        ;to 0000 xxxx  in bcd

                        movlw   0x30

                        addwf   ds2,same        ;bcd to ascii numeral    &n;      

                        movlw   00001111b

                        rrf     ds3,same

                        andwf   ds3,same        ;to 0000 xxxx  in bcd

                        movlw   0x30

                        addwf   ds3,same        ;bcd to ascii numeral    &n;      

                        movlw   00001111b

                        rrf     ds4,same

                        andwf   ds4,same        ;to 0000 xxxx  in bcd

                        movlw   0x30

                        addwf   ds4,same        ;bcd to ascii numeral    &n;      

                return

;********************************************specific adc mc14433 routines end



;********************************************specific rs232 routines start



;TXBYTE: sends 1 byte @9600 baud, rs232

;uses 1ram, 15(16) rom, 1043 cycles, enters with data in w, exits with w trashed

;pic xtal clock at 4mhz. The routine sets the data format a 8N1 = 8 data, no

;parity, 1 start, 1 stop bits.

;increase the .10 (=10 dec)value after `movwf temp' if you need more stop bits.

;this will affect the cycle times mentioned.

;note that w is used as the delay counter.

;the output data is `inverted' ie a mark is LO and space is HI

;this can be reversed to `correct logic' by swopping the bcf/bsf instructions.

;- in the txloop ONLY, stupoid, JS

;copyright (C) 1995 Dwayne Reid. May be freely used so long as this copyright

;notice is retained.

txbyte                  ;send byte in w at 9600 baud (4mhz osc), 8N1

                movwf   tx_buff

                movlw   0x0A            ;reid's setting=0x0A=10dec =8data+1start+1 stop (incr for more stop bits)

                bcf     status,c        ;initial `0' (=HI) for start bit.

txloop                                  ;bit time=104.167 uSec  

                btfsc   status,c

                bcf     SERTX           ;nb-js, there is no mirror here! reid's = bsf

                btfss   status,c        ;let's suck it & see, maybe no need

                bsf     SERTX           ;reid's = bcf

dloop                                   ;95 clk cycle delay

                goto    $+1             ;2-cycle NOP in 1 instruction!

                addlw   00010000b       ;increment upper nibble

                btfss   status,c        ;delay=6n-1(1 less when falls thru)

                goto    dloop           ;loop 16 times

                addlw   -1              ;dec w,valid z,c=1 if w>=0 after decrement

                rrf     tx_buff,same    ;carry will be set-shifted in as stop bit

                btfss   status,z

                goto    txloop          ;txloop is 104 cycles

        return



powerup_dump    ;dumps startup initial lines to printer

                call    cr_lf           ;set head to newline, left

                clrf    pr01            ;reset pointer offset to 0

                call    hole_space      ;10 spaces right

powerup_dump1

                movf    pr01,w

                call    powerup_table1

                call    txbyte

                incf    pr01,same

                movlw   40              ;decimal 40, lets try decimal today

                xorwf   pr01,w

                btfss   status,z

                goto    powerup_dump1

                call    cr_lf   

                call    cr_lf           ;send a blank line

                call    crush_dump      ;send out date, index etc

        return



crush_dump              ;dumps data line to printer

                call    rclock          ;fetch rtc up-to-date regs

                call    read_eeprom     ;fetch the current non-vol index

                call    hole_space      ;put 10 chars

                movlw   0x90

                subwf   year,w

                btfss   status,c        ;c cleared if we're in 19xx years

                goto    crush_dump1

                movlw   0x31            ;=1 in ascii

                call    txbyte          ;       char1

                movlw   0x39            ;=9 in ascii

                call    txbyte          ;       char2

                goto    crush_dump2

crush_dump1                             ;or...  year 2000+

                movlw   0x32            ;=2 in ascii

                call    txbyte          ;       char1

                movlw   0x30            ;=0 in ascii

                call    txbyte          ;       char2

crush_dump2

                movf    year,w          

                call    packBCD_to_ascii        ;char3...char4

                movlw   0x2F            ; /

                call    txbyte          ;       char5

                movf    month,w

                call    packBCD_to_ascii        ;char6...char7

                movlw   0x2F            ; /

                call    txbyte          ;       char8

                movf    date,w

                call    packBCD_to_ascii        ;char9...char10

                movlw   0x20            ; sp

                call    txbyte          ;       char11

                movlw   0x20            ; sp

                call    txbyte          ;       char12

                movf    hour,w

                call    packBCD_to_ascii        ;char13...char14

                movlw   0x3A            ;

                call    txbyte          ; :     char15

                movf    minute,w

                call    packBCD_to_ascii        ;char16...char17

                movlw   0x3A            ; 

                call    txbyte          ; :     char18

                movf    second,w

                call    packBCD_to_ascii        ;char19...char20           sp;    

                movlw   0x20            ; sp

                call    txbyte          ;       char21

                movlw   0x20            ; sp

                call    txbyte          ;       char22

                clrf    buff_4          ;fetch eeprom index regs

                movf    samp_index3,w   ;most sig eeprom

                movwf   buff_3          ;load input buffers for binary to bcd

                movf    samp_index2,w   ;next sig eeprom

                movwf   buff_2          ;load input buffers for binary to bcd

                movf    samp_index1,w   ;least sig eeprom

                movwf   buff_1          ;load input buffers for binary to bcd

                call    bin2bcd         

                movf    temp_c,w        

                call    packBCD_to_ascii        ;char23...char24           sp;    

                movf    temp_d,w

                call    packBCD_to_ascii        ;char25...char26        

                movf    temp_e,w

                call    packBCD_to_ascii        ;char27...char28        

                movlw   0x20            ; sp

                call    txbyte          ;       char29

                movlw   0x20            ; sp

                call    txbyte          ;       char30

        movf    ds1,w           ;most sig. adc ascii numeral

        call    txbyte          ;       char31

        movf    ds2,w

        call    txbyte          ;       char32          

        movf    ds3,w

        call    txbyte          ;       char33          

        movf    ds4,w

        call    txbyte          ;       char34              sp;   

                movlw   0x20            ; sp

                call    txbyte          ;       char35

                movlw   0x6B            ; k

                call    txbyte          ;       char36

                movlw   0x4E            ; N

                call    txbyte          ;       char37

                movlw   0x20            ; sp

                call    txbyte          ;       char38

                movlw   0x20            ; sp

                call    txbyte          ;       char39

                movlw   0x20            ; sp

                call    txbyte          ;       char40

                call    cr_lf           ;end of line,  

        return



packBCD_to_ascii        ;takes packed bcd byte in w -> ascii ->tx rs232 HI nibble first

                movwf   scratch         ;eg w=98 scratch=98 for years, say

                movwf   scratch1

                swapf   scratch,same    ;eg scratch=89

                movlw   0x0F            ;mask nibble for years 10s

                andwf   scratch,same    ;eg scratch=09

                movlw   0x30            ;convert to ascii

                addwf   scratch,w       ;eg scratch=39 , produces years 10s , in ascii, in w

                call    txbyte          ;       char out  HI nibble

                movf    scratch1,w      ;eg year=98

                movwf   scratch         ;eg scratch=98

                movlw   0x0F            ;mask nibble for years units       &nbspbsp;                   

                andwf   scratch,same    ;eg scratch=08

                movlw   0x30            ;convert to ascii

                addwf   scratch,w       ;eg scratch=38          ="8"

                call    txbyte          ;       char out LO nibble

        return          



cr_lf           ;carriage return + line feed to rs232 port

                        movlw   0x0D            ;CR

                        call    txbyte

                        movlw   0x0A            ;LF

                        call    txbyte

                return          



hole_space      ;space print 10 chars from left of page

                movlw   0x0A

                movwf   scratch

                movlw   0x20    ;ascii `space'  

                call    txbyte

                decfsz  scratch,same

                goto    $-3

        return  

;********************************************specific rs232 routines end



;*********************************************specific bcd handling routines start



;Date:    Mon, 16 Mar 1998 14:18:12 -0600

;From:    Bob Fehrenbach 

;Subject: Re: 32 bits binary to BCD convert?

;>Does anyone know how to convert 32 bits binary to BCD format?

;There probably faster routines but this should do the job.

    ;Binary - BCD   32 bits

    ;Input in buff_4|buff_3|buff_2|buff_1,

    ;

    ;Converts to *packed* bcd in temp_a, temp_b, temp_c, temp_d and temp_e

    ;with the MSD temp_a.

    ;Handles full range:  ff ff ff ff -> 4,294,967,296

    ;Also uses temp_f and count.

    ;2940 cycles including call and return.



bin2bcd:

   bcf     status, c

   movlw   32

   movwf   count5

   clrf    temp_a

   clrf    temp_b

   clrf    temp_c

   clrf    temp_d

   clrf    temp_e

bin2bcd_loop:

   rlf     buff_1, same

   rlf     buff_2, same

   rlf     buff_3, same

   rlf     buff_4, same

   rlf     temp_e, same

   rlf     temp_d, same

   rlf     temp_c, same

   rlf     temp_b, same

   rlf     temp_a, same

   decfsz  count5, same

   goto    adj_dec

   goto    done

adj_dec:

   movlw   temp_e

   movwf   fsr

   call    adj_bcd

   movlw   temp_d

   movwf   fsr

   call    adj_bcd

   movlw   temp_c

   movwf   fsr

   call    adj_bcd

   movlw   temp_b

   movwf   fsr

   call    adj_bcd

   movlw   temp_a

   movwf   fsr

   call    adj_bcd

   goto    bin2bcd_loop

adj_bcd:

   movlw   h'3'

   addwf   indf, w

   movwf   temp_f

   btfsc   temp_f, 3

   movwf   indf

   movlw   h'30'

   addwf   indf, w

   movwf   temp_f

   btfsc   temp_f, 7

   movwf   indf

   return

done:

   return



incw_bcd        ;increment a packed bcd 8bit freg., enter with data in w

                ;ex T Scott Dattalo, 20/4/98

                movwf   scratch

                movlw   11111110b

                addlw   0x9A+1

                subwf   scratch,w

                rlf     scratch,same

                btfss   status,dc

                addlw   -0x06

                btfss   scratch,0

                addlw   -0x60

                rrf     scratch,same    ;result in w

        return          



decw_bcd        ;decrement a packed bcd freg., enter sub with data in w

                ;ex T Scott Dattalo, 20/4/98

                movwf   scratch

                movlw   1

                subwf   scratch,w

                rlf     scratch,same

                btfss   status,dc

                addlw   -0x06   

                btfss   scratch,0

                addlw   -0x60

                rrf     scratch,same    ;result in w

        return



inc_minute_bcd  ;incr minutes reg by 1, check for not overflow 60s

                movf    minute,w

                sublw   0x60            ;59hex means 59dec in packed bcd

                btfsc   status,z

                return                  ;z got set if minutes=59,so don't incr

                movf    minute,w

                call    incw_bcd

                movwf   minute

        return

dec_minute_bcd  ;decrement minute reg, check for zero underflow

                movf    minute,w

                btfsc   status,z

                return                  ;underflow danger, don't decr

                call    decw_bcd

                movwf   minute

        return



inc_hour_bcd    ;incr hours, packed bcd representation

                movf    hour,w

                sublw   0x24

                btfsc   status,z

                return

                movf    hour,w

                call    incw_bcd

                movwf   hour

        return

dec_hour_bcd    ;decrement hour reg, check for zero underflow

                movf    hour,w

                btfsc   status,z

                return                  ;underflow danger, don't decr

                call    decw_bcd

                movwf   hour

        return



inc_date_bcd    ;incr date of month,packed bcd,cheat & assume all months <= 28days

                movf    date,w

                sublw   0x28

                btfsc   status,z

                return

                movf    date,w

                call    incw_bcd

                movwf   date

        return

dec_date_bcd    ;decrement date reg, check for zero underflow

                movf    date,w

                btfsc   status,z

                return                  ;underflow danger, don't decr

                call    decw_bcd

                movwf   date

        return



inc_month_bcd   ;incr month,packed bcd

                movf    month,w

                sublw   0x12

                btfsc   status,z

                return

                movf    month,w

                call    incw_bcd

                movwf   month

        return

dec_month_bcd   ;decrement date reg, check for zero underflow

                movf    month,w

                btfsc   status,z

                return                  ;underflow danger, don't decr

                call    decw_bcd

                movwf   month

        return



inc_year_bcd    ;incr year, packed bcd

                movf    year,w

                sublw   0x99

                btfsc   status,z

                return

                movf    year,w

                call    incw_bcd

                movwf   year

        return

dec_year_bcd    ;decrement date reg, check for zero underflow

                movf    year,w

                btfsc   status,z

                return                  ;underflow danger, don't decr

                call    decw_bcd

                movwf   year

        return



;*********************************************specific bcd handling routines end



;*********************************************gen. purpose subroutines follow



delay           movlw   0x001           ;standard delay routine. increase w value

                movwf   count1          ; for increased delay

                movlw   0x001           ;can set up any delay by calling delay1 (NB!)

                movwf   count2          ; with pre-set values in count1, 2, 3

                movlw   0x020           ;ex Myke Predko, piclist 4 Jan97

                movwf   count3          ;delay, (no of instructions)=

delay1          decfsz  count3,same     ;2 + 5*(count3-1) +

                goto    $-1             ;2 + (5*255 +2+5) * (count2-1) +

                decfsz  count2,same     ;2 + (5*255*256 +2 + 5*255 +2+5) *(count1-1)

                goto    $-3             ;  =

                decfsz  count1,same     ;5(count3-1)+1282(count2-1)+327684(count1-1)+6           &nb     

                goto    $-5             ;

        return                  ;



delay_25us      movlw   0x01            ;25uSec delay

                movwf   count1

                movlw   0x01

                movwf   count2

                movlw   0x06

                movwf   count3

                call    delay1

        return

delay_100us     movlw   0x01            ;100uSec delay

                movwf   count1

                movlw   0x01

                movwf   count2

                movlw   0x13

                movwf   count3

                call    delay1

        return

delay_200us     movlw   0x01            ;200uSec delay

                movwf   count1

                movlw   0x01

                movwf   count2

                movlw   0x26

                movwf   count3

                call    delay1

        return

delay_1ms       movlw   0x01            ;1msec delay

                movwf   count1

                movlw   0x01

                movwf   count2

                movlw   0xC8

                movwf   count3

                call    delay1

        return

delay_100ms     movlw   0x01            ;100msec delay

                movwf   count1

                movlw   0x4E

                movwf   count2

                movlw   0x01

                movwf   count3

                call    delay1

        return

delay_1sec      movlw   0x04            ;1 second delay

                movwf   count1

                movlw   0x0E

                movwf   count2

                movlw   0x38

                movwf   count3

                call    delay1

        return



delay_10sec     movlw   0x1F            ;10 second delay

                movwf   count1

                movlw   0x85

                movwf   count2

                movlw   0x34

                movwf   count3

                call    delay1

        return



;********************General purpose 16F84 EEPROM register read/write

;The following `eprom write' routine requires that eeadr @ loc 0x009

;in bank0 contains the address of the eeprom data byte to be loaded.

;The data must be pre-loaded in eedata @ loc 0x008 in bank0

;In addition, the  eecon1,wren   bit in bank1 regs. must be set before 

;calling this routine. Then cleared after using it.

;ie             bsf     status,rp0              & vice-versa at at finish

;               bsf     eecon1,wren

;               bcf     status,rp0



eeprom_wr                       ;write byte to eeprom loc.

        bcf     intcon,gie      ;make sure ints disabled, work on bank1

        btfsc   intcon,gie      ;to-be-suuuure

        goto    $-1

        bsf     status,rp0      ;set to bank 1,see c84 para 7.2

        movlw   0x055           ;fairy-godmother value, given by uchip

        movwf   eecon2          ;-actually for diode pump charging hv cell drives-

        movlw   0x0AA           ;another fairy-godmother value

        movwf   eecon2

        bsf     eecon1,eewr     ;set write control bit & begin write

        btfsc   eecon1,eewr     ;poll write control bit until h/w resets it LO

        goto    $-1             ;write until job done

        bcf     eecon1,eeif     ;must clear this bit, don't know why??

        bcf     status,rp0      ;bank 0

                ;enable global ints here, if using them.ie  bsf  intcon,gie

        return



;following routine requires eeadr to be pre-loaded with the eeprom location

;--like a pointer. The contents of the location are returned in eedata reg.

eeprom_rd                       ;read byte value from eeprom ->w reg

        bsf     status,rp0      ;bank 1

        bsf     eecon1,eerd     ;ee read

        bcf     status,rp0      ;bank 0

        return



inc_eeprom              ;increment eeprom regs 00,01,02

        call    read_eeprom     ;fetch all eeprom vals to 16f84 fregs   

        incfsz  samp_index1,same

        goto    inc_eeprom1

        incfsz  samp_index2,same

        goto    inc_eeprom1

        incfsz  samp_index3,same

        goto    inc_eeprom1

inc_eeprom1

        movf    samp_index1,w

        movwf   eedata

        movlw   0x01

        movwf   eeadr   

        bsf     status,rp0

        bsf     eecon1,wren

        bcf     status,rp0

        call    eeprom_wr

        bsf     status,rp0

        bcf     eecon1,wren

        bcf     status,rp0

        movf    samp_index2,w

        movwf   eedata

        movlw   0x02

        movwf   eeadr   

        bsf     status,rp0

        bsf     eecon1,wren

        bcf     status,rp0

        call    eeprom_wr

        bsf     status,rp0

        bcf     eecon1,wren

        bcf     status,rp0

        movf    samp_index3,w

        movwf   eedata

        movlw   0x03

        movwf   eeadr   

        bsf     status,rp0

        bsf     eecon1,wren

        bcf     status,rp0

        call    eeprom_wr

        bsf     status,rp0

        bcf     eecon1,wren

        bcf     status,rp0

        return



read_eeprom             ;fetch tha values of ALL eeprom 01,02,03

        movlw   0x01

        movwf   eeadr

        call    eeprom_rd

        movf    eedata,w

        movwf   samp_index1

        movlw   0x02

        movwf   eeadr

        call    eeprom_rd

        movf    eedata,w

        movwf   samp_index2

        movlw   0x03

        movwf   eeadr

        call    eeprom_rd

        movf    eedata,w

        movwf   samp_index3

        return



;**************************************************end of  g.p. subroutines



;**************************************************start of isr

service                                         ;dummy el for isr



        retfie

;**************************************************end of isr



                end



















Interfacing the DS5000 to the DS1307 By Dallas Semiconductor
/***************************************************************************/

/*                                          &p;                              */

/* EX1307C_2W.TXT                                       &nbsnbsp;                 */

/* This file is provided to show an example of communication routines for  */

/* interfacing the DS5000 to the DS1307.                                   */

/* These routines are provided for example only and are not supported by   */

/* by Dallas Semiconductor.                                      sp;         */ 

/***************************************************************************/

#pragma code symbols debug 

#include <stdio.h>                  /* Prototypes for I/O functions        */

#include <DS5000.h>                /* Register declarations for DS5000     */

sbit scl = P1^0;        /* 2-wire pin definitions */

sbit sda = P0^0;

void Start2W();

void Stop2W();

void WriteByte2W(unsigned char d);

unsigned char ReadByte2W();

unsigned char ReadNack2W();

void WriteByte1307();

void Initialize_DS1307();

void Disp_Clk_Regs();

void BurstRamRead();

/* ----------------------------------------------------------------------- */

void Start2W()

{

  sda = 1;    /* Initiate start condition */

  scl = 1; 

  sda = 0; 

}

/* ----------------------------------------------------------------------- */

void Stop2W()

{

  sda = 0;    /* Initiate stop condition */

  sda = 0;    

  sda = 0;   

  sda = 0;    

  sda = 0;   

  scl = 1; 

  scl = 1; 

  sda = 1; 

}

/* ----------------------------------------------------------------------- */

void WriteByte2W(unsigned char d)

{

  int i;



  scl = 0;  

  for (i=1;i<=8;i++) {

    if (d & 0x80) sda = 1; /* Send the msbits first */

      else sda = 0;

    scl = 0;  

    scl = 1;  

    scl = 0;  

    d = d << 1;

  }

  sda = 1;    /* Release the sda line */

  scl = 0;  

  scl = 1;  

  if (sda) printf("Acknowledge bit missing\n");

  scl = 1;  

  scl = 0;  

}

/* ----------------------------------------------------------------------- */

unsigned char ReadByte2W()

{

  int i;

  unsigned char d;



  d = 0;

  sda = 1;             /* Let go of sda line */

  for (i=1;i<=8;i++) { /* read the msb first */

    scl = 0; 

    scl = 1; 

    d = d << 1;

    d = d | (unsigned char)sda;

    scl = 1; 

    scl = 0; 

  }

  sda = 0;          /* Hold sda low for acknowledge */



  scl = 0; 

  scl = 1; 

  scl = 0; 



  sda = 1;          /* Release the sda line */

  return d;

}

/* ----------------------------------------------------------------------- */

unsigned char ReadNack2W()

{

  int i;

  unsigned char d;



  d = 0;

  sda = 1;             /* Let go of sda line */

  for (i=1;i<=8;i++) { /* read the msb first */

    scl = 0; 

    scl = 1; 

    d = d << 1;

    d = d | (unsigned char)sda;

    scl = 1; 

    scl = 0; 

  }

  sda = 0;          /* Hold sda low for acknowledge */



  scl = 0; 

  scl = 1; 

  sda = 1;          /* sda = 1 if next cycle is reset */

  scl = 0; 



  return d;

}



/* ----------------------------------------------------------------------- */

void WriteByte1307()

{

uchar Add;

uchar Data;

/* Get Address & Data */

   printf("\nEnter the Read Address\nADDRESS:");

   scanf("%bx", &Add);

   printf("\nDATA:");

   scanf("%bx", &Data);



   Start2W();

   WriteByte2W(0xD0);

   WriteByte2W(Add);

   WriteByte2W(Data);

   Stop2W();

}

/* ----------------------------------------------------------------------- */

void Initialize_DS1307()

{

/* The following Enabels the Oscillator                                    */

   Start2W();

   WriteByte2W(0xD0);

   WriteByte2W(0x00);

   WriteByte2W(0x00);

   Stop2W();



/* The following Enabels the Square Wave Output at 32KHz                   */

   Start2W();

   WriteByte2W(0xD0);

   WriteByte2W(0x07);

   WriteByte2W(0x13);

   Stop2W();

}

/* ----------------------------------------------------------------------- */

void Disp_Clk_Regs()

{

uchar Sec;

uchar Min;

uchar Hrs;

uchar Dte;

uchar Mon;

uchar Day;

uchar Yr;

/* Read & Display Clock Registers */

   Start2W();

   WriteByte2W(0xD0);

   WriteByte2W(0x00);

   Start2W();

   WriteByte2W(0xD1);

   Sec = ReadByte2W();

   Min = ReadByte2W();

   Hrs = ReadByte2W();

   Day = ReadByte2W();

   Dte = ReadByte2W();

   Mon = ReadByte2W();

   Yr  = ReadNack2W(); 

/*   Yr  = io_read_byte(1); */

   Stop2W();

   printf("\nYr   Mon  Dte  Day  Hrs  Min  Sec");

   printf("\n%2.bX   %2.bX   %2.bX   %2.bX", Yr, Dte, Mon, Day);

   printf("   %2.bX   %2.bX   %2.bX", Hrs, Min, Sec);

}

/* ----------------------------------------------------------------------- */

void BurstRamRead()

{

uchar keypress;

uchar i;

uchar j;

        printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");

        printf("\nDS1307 Ram\n");



   Start2W();

   WriteByte2W(0xD0);

   WriteByte2W(0x08);

   Start2W();

   WriteByte2W(0xD1);

   printf("\n                        ");

      for (j=0; j<8; ++j)

         {

         printf("%2.bX ", ReadByte2W() );

         }

   for (i=0; i<2; ++i)

      {

      printf("\n");

      for (j=0; j<16; ++j)

         {

         printf("%2.bX ", ReadByte2W() );

         }

      }

      printf("\n");

      for (j=0; j<15; ++j)

         {

         printf("%2.bX ", ReadByte2W() );

         }

/*         printf("%2.bX ", io_read_byte(1) ); */

         printf("%2.bX ", ReadNack2W() ); 

   Stop2W();

   printf("\n\nPress a key to return to menu");

        printf("\n\n\n\n\n\n\n\n\n\n\n\n");



   keypress = _getkey();

}

/* ----------------------------------------------------------------------- */

void main (void)

{

uchar i;

uchar M;

uchar M1;

        while (1)

        { 

   printf("\n\n\n");

   printf("DS1307\n");

   printf("CI. Initialize DS1307 \n");

   printf("CW. Write Byte\n");

   printf("CR. Read Time\n");

   printf("RR. Read Ram\n");

   printf("\n\n\n");

   printf("\nEnter Menu Selection:");



M = _getkey();



   switch(M) 

      {

           case 'C':

           case 'c':

         printf("\rEnter Clock Routine to run:C");

         M1 = _getkey();



         switch(M1) 

            {

            case 'I':

            case 'i':

                      Initialize_DS1307();

            break;



            case 'R':

            case 'r':

              Disp_Clk_Regs();

              break;



            case 'W':

            case 'w':

              WriteByte1307(); 

            break;

            }



           break;

           case 'R':

           case 'r':

         printf("\rEnter Ram Routine to run:R");

         M1 = _getkey();



         switch(M1) 

            {

            case 'R':

            case 'r':

              BurstRamRead();

                 break;

            }



           break;

      }

   }

}

DS1302 from port d on an 8535 (SIMM100), 

written in asm using AVRA assembler by Ingmar Meins
 .include "c:\avr\appnotes\8535def.inc" ; This stuff defines name for ports etc.

;

; *************************************************

; DS1302 test software written by I.Meins 20/2/01.

;

; Tested with DS1302 connected to Port D on SIMM100

; with PD4 to RST, PD5 to I/O and PD6 to SCLK.

;

; Main routines are the WrtCmd and RdCmd routines.

; They handle the clocking in and out of data.

; *************************************************



.dseg

;

.equ    TRUE = $FF ;Yes

.equ    FALSE =$00 ;No

;

.equ    XTAL =8000000

.equ    BAUDRATE = 51   ; 9600.

.equ    RXOK = 1        ; Got a RX character.



;

; *****************

; ASCII Equivalents

; *****************

;

.equ    NUL=$00 ;Null

.equ    SOH=$01 ;Start of Header

.equ    STX=$02 ;Start of Text

.equ    ETX=$03 ;End of Text

.equ    EOT=$04 ;End of Transmission

.equ    ENQ=$05 ;Enquiry

.equ    ACK=$06 ;Acknowlege

.equ    BEL=$07 ;Bell

.equ    BS=$08 ;Backspace

.equ    HT=$09 ;Horizontal Tab

.equ    LF=$0A ;Line Feed

.equ    VT=$0B ;Vertical Tab

.equ    FF=$0C ;Form Feed

.equ    CR=$0D ;Carriage Return

.equ    SO=$0E ;

.equ    SI=$0F ;

;

.equ    DLE=$10 ;Delete

.equ    XON=$11 ;AKA DC1

.equ    XOFF=$12 ;AKA DC2

.equ    DC3=$13 ;

.equ    DC4=$14 ;

.equ    NAK=$15 ;Negative Acknowlege

.equ    SYN=$16 ;Sync 

.equ    ETB=$17 ;

.equ    CAN=$18 ;Cancel

.equ    EM=$19 ;

.equ    SUB=$1A ;

.equ    ESC=$1B ;

.equ    FS=$1C ;Field Separator

.equ    GS=$1D ;Group Separator

.equ    RS=$1E ;Record Separator

.equ    US=$1F ;

;

; *****************************************************************

; Define some standard name for a few registers that will be shared

; all over the place.

; *****************************************************************

;

; Servo pulse width settings for various speeds and directions of the

; main drive motors.

;

.def    TEMP1 = R16

.def    TEMP2 = R17

.def    Param1 = R18

.def    Flags = R19

.def    WaitLp = R20

;

; R1 - 

; R2 - 

; R3 - 

; R4 - 

; R5 - 

; R6 -

; R7 -

; R8 -

; R9 - 

; R10 -

; R11 -

; R12 -

; R13 -

; R14 -

; R15 -

; R16 - TEMP1 - General non-isr garbage store.

; R17 - TEMP2 - General non-isr garbage store.

; R18 - Param1 - To pass parameters to subroutines.

; R19 - Flags - 

; R20 - Wait loops.

; R21 - 

; R22 - 

; R23 - 

; R24 - To save SREG in ISR for Timer 0.

; R25 - 

;

; ***************************************************************

; Remember that register pairs X,Y,Z are used for special things.

; ***************************************************************

;

.def    XL =R26

.def    XH =R27

.def    YL =R28

.def    YH =R29

.def    ZL =R30

.def    ZH =R31

;

; ****************************************************

; Now we define the names for specific SRAM locations.

; ****************************************************

;

.org 0x60 ;The beginning of RAM (Since we are in a DSEG)

;

; *********************************************************************

; Now we change to the code segment where the real program code starts.

; *********************************************************************

;

.cseg



; wait <number of cycles>, <register to use for count>



.macro wait

.if @0 > 765

.error "Wait macro: Too high wait value!"

.endif



.if @0 < 3

.if @0 >= 1

        nop

.if @0 >= 2

        nop

.endif

.endif

.else

        ldi     @1, @0 / 3

waitloop:

        dec     @1

        brne    waitloop

.if (@0 % 3) >= 1

        nop

.if (@0 % 3) >= 2

        nop

.endif

.endif

.endif

.endmacro



.macro IO_In

        cbi             DDRD,5                  ; Make I/O line input.

.endmacro



.macro IO_Out

        sbi             DDRD,5                  ; Make I/O line output.

.endmacro



.macro SCLK_h

        nop

        sbi             PORTD,6                 ; Set SCLK output.

        nop

.endmacro



.macro SCLK_l

        nop

        cbi             PORTD,6

        nop

.endmacro



.macro  IO_h

        sbi             PORTD,5

.endmacro



.macro  IO_l

        cbi             PORTD,5

.endmacro



.macro  RST_h

        sbi             PORTD,4

.endmacro



.macro  RST_l

        cbi             PORTD,4

.endmacro



;

; ********************************************************

; Fixed jump vectors for the system interrupts and resets.

; ********************************************************

;

;$000

                rjmp    INIT_Machine    ;Restart vector, points to the beginning of the code. 

;$001

        reti                            ;IRQ 0

;$002

        reti                    ;IRQ 1

;$003 

        reti                    ;Timer/Counter 2 Output compare match interrupt.

;$004

        reti                    ;Timer/Counter 2 Overflow interrupt.

;$005

        reti                    ;Timer/Counter 1 Input capture interrupt.

;$006

        reti                    ;Timer/Counter 1 Output compare A match.

;$007 

        reti                    ;Timer/Counter 1 Output compare B match.

;$008 

        reti                            ;Timer/Counter 1 Overflow interrupt.

;$009

        reti                            ;Timer/Counter 0 Overflow interrupt.

;$00A

        reti                    ;SPI Serial transfer complete interrupt.

;$00B

        reti                    ;Uart RX complete.

;$00C

        reti                    ;Uart TX data register empty.

;$00D

        reti                    ;Uart TX complete.

;$00E

        reti                    ;Analogue conversion complete.

;$00F

        reti                    ;EEPROM Ready.

;$010

        reti                    ;Analogue comparator interrupt.

;

;

; **************************************

; This is the start of the program code.

; **************************************

;

INIT_Machine:

        ldi     R24,$1f                 ; Disable the watchdog.

    out         $21,R24

    ldi         R24,$17

    out         $21,R24

    ldi         R24,$5F         ; Setup the stack pointer to top of ram.

    out         $3D,R24

    ldi         R24,$02

    out         $3E,R24



        rcall   SetupUart               ; Setup the serial port.

        rcall   SetupIO         ; Setup IO configuration.





; *************************************************

; Actual program code goes here for the loop.......

; *************************************************



        rjmp    Mon



; *******************************************************************

; Monitor command processor.

; *******************************************************************



Mon:

;       rcall   Uart_RX



        ldi             Temp1,$8E

        ldi             Temp2,$00

        rcall   WrtCmd



;       RCALL   Uart_RX



        ldi             Temp1,$80

        ldi             Temp2,$00

        rcall   WrtCmd

;       rcall   Uart_RX



        ldi     ZL,low(Greeting*2)              ; Send startup msg.

        ldi     ZH,high(Greeting*2)

        rcall   TX_Str



MTop:

        rcall   CRLF                            ; CR/LF.



        ldi     ZL,low(Prompt*2)                ; OK> prompt.

        ldi     ZH,high(Prompt*2)

        rcall   TX_Str



MKbloop:

        rcall   Uart_RX                         ; Get a character.



        cpi     Param1,'s'                              ; Seconds ?

        brne    M0                                      ; Branch to next test if not 's'.



        rcall   CRLF

        ldi             Temp1,$81                       ; read seconds.

        rcall   RdCmd

        rcall   Dump_Nibbles

        rcall   CRLF

        rjmp    Mtop



M0:

        cpi     Param1,'m'                              ; Minutes ?

        brne    M1                                      ; Branch to next test if not 'm'.



        rcall   CRLF

        ldi             Temp1,$83                       ; read seconds.

        rcall   RdCmd

        rcall   Dump_Nibbles

        rcall   CRLF

        rjmp    Mtop



M1:

        cpi     Param1,'h'                              ; Hours ?

        brne    M2                                      ; Branch to next test if not 'h'.



        rcall   CRLF

        ldi             Temp1,$85                       ; read seconds.

        rcall   RdCmd

        rcall   Dump_Nibbles

        rcall   CRLF

        rjmp    Mtop



M2:

        cpi     Param1,'t'                              ; Time ?

        brne    Mkb1                            ; Branch to next test if not 't'.



        rcall   CRLF

        ldi             Temp1,$85                       ; read hours.

        rcall   RdCmd

        rcall   Dump_Nibbles



        ldi             Temp1,$83                       ; read minutes.

        rcall   RdCmd

        rcall   Dump_Nibbles



        ldi             Temp1,$81                       ; read seconds.

        rcall   RdCmd

        rcall   Dump_Nibbles

        rcall   CRLF

        rjmp    Mtop



Mkb1:

        ldi     ZL,low(A_Huh*2)                 ; Huh ?

        ldi     ZH,high(A_Huh*2)

        rcall   TX_Str



        rcall   CRLF                            ; Next line.

        rjmp    Mtop



A_Huh:

        .db     " Huh ?",0





; Write a cmd / data combo from Temp1 / Temp2 to the RTC.



WrtCmd:

        RST_h

        mov             Param1,Temp1

        rcall   WrtByte

        mov             Param1,Temp2

        rcall   WrtByte

        RST_l

        ret



; Read a byte following write of command byte.



RdCmd:

        RST_h

        mov             Param1,Temp1

        rcall   WrtByte

        rcall   RdByte

        RST_l

        ret



; Clock out the byte in Param1 to the RTC.

; Data is clocked out starting with bit 0. Data is clocked into the RTC on the rising edge.



WrtByte:

        IO_Out  

        push    Temp1

        ldi             Temp1,8                         ; 8 bits to clock out.



WrtByte1:

        lsr             Param1                          ; rotate bit 0 into C

        brcc    WrtByte2                        ; skip if bit = 0



        IO_h

        rjmp    WrtByte3



WrtByte2:

        IO_L



WrtByte3:

        SCLK_h

        dec             Temp1

        breq    WrtByte4



        SCLK_l                                          ; Clock it out.

        rjmp    WrtByte1                        ; Do all the bits.



WrtByte4:

        IO_In                                           ; Switch to input mode.

        IO_h                                            ; turn on pull up.

        SCLK_l                                          ; Clock data in (if applicable).

        pop             Temp1

        ret



; Clock in a byte from the RTC to Param1



RdByte:

        ldi             Param1,0

        ldi             Temp1,8                         ; 8 bits to clock in.



RdByte1:

        clc                                                     ; Clear carry.

        sbic    PIND,5                          ; Jump if I/O = 0.

        sec

        ror             Param1                          ; Rotate data into bit.

        SCLK_h                                          ; clock in next bit.

        SCLK_l

        dec             Temp1                           ; more bits ?

        brne    RdByte1

        ret



        

; *********************************************************

; Dump_Nibbles: Send byte Param1 to RS232 as ASCII nibbles.

; *********************************************************

;

Dump_Nibbles:

        push    Param1

        rcall   NibH2Asc

        rcall   Uart_TX

        pop     Param1

        rcall   NibL2Asc

        rcall   Uart_TX



        ret



;

; **************

; Some messages.

; **************

Prompt:

        .db     "Ok> ",0

Greeting:

        .db     0x0d,0x0a,"DS1302",0x0d,0x0a,0x0a,0x0a

        .db "Commands: t - time, h,s,m - show hours/minutes/seconds",0x0d,0x0a,0x0a,0



; ***************************

; CRLF - send CRLF out RS232.

; ***************************

;

CRLF:

        push    Param1

        ldi     Param1,CR

        rcall   Uart_TX

        ldi     Param1,LF

        rcall   Uart_TX

        pop     Param1



        ret



; ***********************************

; SetupIO

; Setup the IO pins to suit this

; particular project.

; ***********************************

;

SetupIO:

        ldi     r16,0

        out     PORTD,r16



        ldi     r16,$ff                 ; All outputs to start with.

        out     DDRD,r16



    ret



; *****************************************************

; Set the hardware UART for non-interrupt TX/RX and

; set baudrate to value in BAUDRATE, eg 8MHz 25 = 19200

; *****************************************************

;

SetupUart:

        ldi     Temp1,BAUDRATE

        out     UBRR,Temp1

        ldi     Temp1,$18       ; TX/RX 8 bits, no irq.

        out     UCR,Temp1       



        ret



; ********************************************

; Send the byte in Param1 out the serial port.

; ********************************************

;

Uart_TX:

        sbis    USR,UDRE        ; Check if TX empty.

        rjmp    Uart_TX         ; Loop till ready to TX.



        out     UDR,Param1      ; Send the byte.



        ret



; ***********************************************************

; Receive a byte from the Uart if available, waits till ok.

; Return it in Param1.

; ***********************************************************

;

Uart_RX:

        sbis    USR,RXC         ; Check ready flag.

        rjmp    Uart_RX         ; Loop till available.



        in      Param1,UDR      ; Get character.



        ret

        

; ****************************************************

; Convert the nibble in Param1 to ASCII hex in Param1.

; ****************************************************

;

NibH2Asc:

        swap    Param1          ; Swap nibbles.

NibL2Asc:

        push    temp2           ; Save work register.



        andi    Param1,$0f      ; Isolate lower nibble.

        ldi     Temp2,$30

        cpi     Param1,10       ; Check if lower then 10.

        brlo    Nib2Asc1

        

; Nibble + $30 = '0' - '9'

; Nibble + $37 = 'A' - 'F'



        ldi     Temp2,$37

Nib2Asc1:

        add     Param1,Temp2

        pop     temp2



        ret



; ****************************************************

; Send a string from ROM to Uart. Terminated with $00.

; Start address in Z ie. R30/31. ZL and ZH.

; ****************************************************



TX_Str:

        lpm                     ; Load byte into R0.

        or      R0,R0           ; Check if EOT, null.

        breq    TX_StrE



        mov     Param1,R0       ; Not a null so send.

        rcall   Uart_TX

        adiw    ZL,$01          ; Next byte.

        rjmp    TX_Str          ; Keep going....



TX_StrE:

        ret





; ****************************************

; DelayUs

; Delay for the number of uS given in

; register Param1.

;

; 8 + ((Param1 - 1) * 2) + (Param1 * 6)

; ****************************************

;

DelayUs:

        dec     Param1

DelayUs1:                       ; 3 / 4

        nop                     ; 1 cycle.

        nop                     ; 1 cycle.

        nop                     ; 1 cycle.

        nop                     ; 1 cycle.

        nop                     ; 1 cycle.

        dec     Param1          ; 1 cycle.

        brne    DelayUs1        ; 2 for each until done then 1 cycle.

        ret                     ; 4 cycles.



Dontronics Home Page
_
Copyright © 1996-2006 Dontronics

Top of Page