DS1302, TWI and Assembler

Go To Last Post
22 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm struggling to understand the Atmel explanation of TWI.

 

To speak to a DS1302 RTC, so I need all that stuff about addressing a slave etc.?

 

Can I just:

 

Wire RST on the clock module high.

 

Clock out commands and then clock in the data as per the DS1302 datasheet, without doing anything fancy?

 

Or do I have to do something fancy to tell the clock I'm talking to it?

It's me again...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From memory, the DS1302 is either SPI or some weird non-standard protocol.

The DS1307 and other variants is an I2C device.

No, you do not need to use SPI or TWI hardware with a Master. Just go ahead and bit-bang to your heart's content.

David,

p.s. hard-wiring any RESET pin is unwise (tm)

Last Edited: Tue. Apr 5, 2016 - 12:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks,

 

Can I use the hardware TWI interface though?

 

 

It's me again...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First off,  you need to read the number on your chip.

 

I have just looked at the DS1302 data sheet.   it is an "SDIO" interface.   i.e. you can NOT use the mega's SPI peripheral.

 

Obviously,  the TWI peripheral can NOT be used for an SDIO chip.   Of course you can bit-bang SDIO using the TWI pins.    This means that you can no longer use the TWI bus for genuine I2C chips.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Bit bang it is :-)

 

Probably for the best as I have other uses for one of the TWI pins!

 

Thanks!

It's me again...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So you really do have a DS1302 chip ?

Judging by the monster ASM listing that you posted earlier, you have your work cut out already.

Have you inherited someone else's project?
It is not impossible to maintain ASM projects. Just expect regular nightmares.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
So you really do have a DS1302 chip ? Judging by the monster ASM listing that you posted earlier, you have your work cut out already.

Repeating some of the above:  With all the roughly comparable RTC chips out there, why is this one chosen if the interface is difficult for the app?  [We tend to use DS1305/6 as many of our apps have SPI peripherals so adding another makes sense.  Your app may have I2C; then use an I2C RTC.  Or serial.  or whatever.]

 

The datasheet sez:

Simple Serial Port Interfaces to Most

Microcontrollers

o

Simple 3

-Wire

Interface

...so how hard could it be? ;)

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are many hits on these forums for DS1302.  And a project:  https://community.atmel.com/proje... Yes, most is in C.  But how hard could it be to translate a "simple" interface?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have written code for a DS1302.   It is not difficult.    It just seems crazy to choose a non-SPI or non-I2C device.

 

Of course,  other makes of MCU can use their SDIO hardware.    The AVR mega can only bit-bang.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I bought it off ebay, I read 'arduino' and assumed it must be easy to interface if the makers can do it ;-)

 

theusch wrote:
There are many hits on these forums for DS1302. And a project: https://community.atmel.com/proje... Yes, most is in C. But how hard could it be to translate a "simple" interface?

 

Only one page for DS1203 + Assembler though - and none is a solution!

 

Interface is simple enough - my main concern was that I am really struggling to understand the little setup dance that TXWI/I2C does before you can exchange data. Shift a byte out, shift one (or more in) is easy.

 

 

It's me again...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Are you being intentionally obstructive?

 

Your typos hardly inspire confidence.    We still don't know whether you have DS1302 or DS1307.   Both are common modules on Ebay.

 

If you want to write in ASM,   simply translate the Arduino sketch.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here we go - I hope this will work...

 

RTC_FETCH_BYTE:                ;fetches a byte into temp.
    cbi        DDRB,RTCDAT
    rjmp    SKIP49
RTC_SEND_BYTE:                ;byte in temp
    sbi        DDRB,RTCDAT
SKIP49:
    sbi        PORTB,RTCRST
    ldi        temp1,8
LOOP01:
    ror    temp
    brcc    SKIP50
    sbi        PORTB,RTCDAT
    rjmp    SKIP51
SKIP50:
    cbi        PORTB,RTCDAT

SKIP51:
    sbi        PORTB,RTCCLK
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    nop                            ;I hate doing this...
    cbi        PORTB,RTCCLK
    dec        temp1
    brpl    LOOP01

    ror        temp                ;haul last bit into temp
    cbi    PORTB,RTCRST
ret

Now I need to make up a cable...

It's me again...

Last Edited: Tue. Apr 5, 2016 - 07:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if it's I2C you will need to change directions of the IO's

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:

if it's I2C you will need to change directions of the IO's

 

That's the section at the top that clears or sets the RTCDAT(a) bit in DDRB.

It's me again...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But that won't work - clearing reset after sending a command byte will end the transfer before any data is sent!

 

 

BAH! Blooming thing uses BCD

 

And decrementing a counter from 8 won't stop at zero if I test it with BRPL instead of BRNE

It's me again...

Last Edited: Wed. Apr 6, 2016 - 07:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

my code is b----

 

please ignore it

It's me again...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

Are you being intentionally obstructive?

 

Your typos hardly inspire confidence.    We still don't know whether you have DS1302 or DS1307.   Both are common modules on Ebay.

 

If you want to write in ASM,   simply translate the Arduino sketch.

 

David.

 

I thought your question was rhetorical - the thread title says DS1302 and so does the writing on the chip...

 

Actually I can't see anywhere where I wrote DS1307 and lots of places where I put DS1302. So why do folk think I may have a DS1307?

 

Anyway, eventually found some C-code on this site that is suitably low-level, and my latest code appears to be correct (it sends the right codes and sets the right pins in the simulator)

 

Problem is, in fact, I broke a track on the module when removing a header so no clock signal is getting through.

 

B***R

It's me again...

Last Edited: Thu. Apr 7, 2016 - 03:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Stub_Mandrel wrote:
Only one page for DS1203 + Assembler though

You do know that C compilers write assembler don't you?

 

For example if I take alank2's project that Lee linked to and copy the ds1302_settings_example.h to ds1302_settings.h (and change the ADELAY setting within) then compile with:

$ avr-gcc -c -DF_CPU=8000000UL -mmcu=atmega16 -Os -save-temps ds1302.c

I get a ds1302.s file that contains this:

	.file	"ds1302.c"
__SP_H__ = 0x3e
__SP_L__ = 0x3d
__SREG__ = 0x3f
__tmp_reg__ = 0
__zero_reg__ = 1
	.text
.Ltext0:
.global	ds1302_shiftout
	.type	ds1302_shiftout, @function
ds1302_shiftout:
//==>   {
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
//==>     DDR(SIO_PORT)|=_BV(SIO_PIN);           // Set SIO to output
	sbi 0x11,3
	ldi r25,lo8(8)
.L4:
//==>         if (AData & _BV(0))                // LSB sent first
	sbrs r24,0
	rjmp .L2
//==>           SIO_PORT|=_BV(SIO_PIN);
	sbi 0x12,3
	rjmp .L3
.L2:
//==>         else SIO_PORT&=~_BV(SIO_PIN);
	cbi 0x12,3
.L3:
//==>         Delay_ns(DS1302_TDC);
	nop
//==>         SCLK_PORT|=_BV(SCLK_PIN);          // Cycle SCLK
	sbi 0x12,2
//==>         Delay_ns(DS1302_CH);
	rjmp .
//==>         SCLK_PORT&=~_BV(SCLK_PIN);
	cbi 0x12,2
//==>         Delay_ns(DS1302_CL);
	rjmp .
//==>         AData>>=1;                         // Prepare to send next bit
	lsr r24
	subi r25,lo8(-(-1))
//==>     while (Bits)
	brne .L4
//==>     DDR(SIO_PORT)&=~_BV(SIO_PIN);          // Set SIO back to input
	cbi 0x11,3
	ret
	.size	ds1302_shiftout, .-ds1302_shiftout
.global	ds1302_shiftin
	.type	ds1302_shiftin, @function
ds1302_shiftin:
//==>   {
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
//==>   {
	ldi r18,lo8(8)
//==>     unsigned int ui1=0;
	ldi r24,0
	ldi r25,0
.L9:
//==>         ui1>>=1;
	lsr r25
	ror r24
//==>         ui1|=(PIN(SIO_PORT) & _BV(SIO_PIN))?128:0;       // LSB received first
	sbic 0x10,3
	rjmp .L10
	ldi r20,0
	ldi r21,0
	rjmp .L8
.L10:
	ldi r20,lo8(-128)
	ldi r21,0
.L8:
//==>         ui1|=(PIN(SIO_PORT) & _BV(SIO_PIN))?128:0;       // LSB received first
	or r24,r20
	or r25,r21
//==>         SCLK_PORT|=_BV(SCLK_PIN);                        // Cycle SCLK
	sbi 0x12,2
//==>         Delay_ns(DS1302_CH);
	rjmp .
//==>         SCLK_PORT&=~_BV(SCLK_PIN);
	cbi 0x12,2
//==>         Delay_ns(DS1302_CL);
	rjmp .
	subi r18,lo8(-(-1))
//==>     while (Bits)
	brne .L9
/* epilogue start */
//==>   }
	ret
	.size	ds1302_shiftin, .-ds1302_shiftin
.global	ds1302_getbyte
	.type	ds1302_getbyte, @function
ds1302_getbyte:
//==>   {
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
//==>     CE_PORT|=_BV(CE_PIN);                                // Set CE high
	sbi 0x12,4
//==>     Delay_ns(DS1302_TCC);
	ldi r25,lo8(2)
1:	dec r25
	brne 1b
	rjmp .
//==>     ds1302_shiftout(AAddress | _BV(0));                  // Send command byte
	ori r24,lo8(1)
	call ds1302_shiftout
//==>     c1=ds1302_shiftin();                                 // Get result
	call ds1302_shiftin
//==>     CE_PORT&=~_BV(CE_PIN);                               // Take CE back low
	cbi 0x12,4
//==>     Delay_ns(DS1302_CWH);
	ldi r25,lo8(2)
1:	dec r25
	brne 1b
	rjmp .
//==>   }
	ret
	.size	ds1302_getbyte, .-ds1302_getbyte
.global	ds1302_setbyte
	.type	ds1302_setbyte, @function
ds1302_setbyte:
//==>   {
	push r28
	push r29
	push __zero_reg__
	in r28,__SP_L__
	in r29,__SP_H__
/* prologue: function */
/* frame size = 1 */
/* stack size = 3 */
.L__stack_usage = 3
//==>     CE_PORT|=_BV(CE_PIN);                                // Set CE high
	sbi 0x12,4
//==>     Delay_ns(DS1302_TCC);
	ldi r25,lo8(2)
1:	dec r25
	brne 1b
	rjmp .
//==>     ds1302_shiftout(AAddress & ~_BV(0));                 // Send command byte
	andi r24,lo8(-2)
	std Y+1,r22
	call ds1302_shiftout
//==>     ds1302_shiftout(AValue);                             // Send value
	ldd r22,Y+1
	mov r24,r22
	call ds1302_shiftout
//==>     CE_PORT&=~_BV(CE_PIN);                               // Take CE back low
	cbi 0x12,4
//==>     Delay_ns(DS1302_CWH);
	ldi r24,lo8(2)
1:	dec r24
	brne 1b
	rjmp .
/* epilogue start */
//==>   }
	pop __tmp_reg__
	pop r29
	pop r28
	ret
	.size	ds1302_setbyte, .-ds1302_setbyte
.global	ds1302_reset_time
	.type	ds1302_reset_time, @function
ds1302_reset_time:
//==>   {
	push r17
	push r28
	push r29
/* prologue: function */
/* frame size = 0 */
/* stack size = 3 */
.L__stack_usage = 3
//==>     ds1302_setbyte(0x8e,0x00);                           // Disable WP
	ldi r22,0
	ldi r24,lo8(-114)
	call ds1302_setbyte
//==>     ds1302_setbyte(0x90,TCS_REGISTER_DEFAULT);           // Set TCS to default
	ldi r22,0
	ldi r24,lo8(-112)
	call ds1302_setbyte
//==>     CE_PORT|=_BV(CE_PIN);                                // Set CE high
	sbi 0x12,4
//==>     Delay_ns(DS1302_TCC);
	ldi r24,lo8(2)
1:	dec r24
	brne 1b
	rjmp .
//==>     ds1302_shiftout(0xbe);                               // Burst write of time sets all registers in sync with each other
	ldi r24,lo8(-66)
	call ds1302_shiftout
	ldi r28,lo8(ResetTime)
	ldi r29,hi8(ResetTime)
	mov r17,r28
	subi r17,lo8(-(8))
.L15:
//==>       ds1302_shiftout(pgm_read_word(ResetTime+c1));
	movw r30,r28
/* #APP */
 ;  147 "ds1302.c" 1
	lpm r24, Z+
	lpm r25, Z
	
 ;  0 "" 2
/* #NOAPP */
	call ds1302_shiftout
	adiw r28,1
//==>     for (c1=0;c1<8;c1++)
	cpse r17,r28
	rjmp .L15
//==>     CE_PORT&=~_BV(CE_PIN);                               // Take CE back low
	cbi 0x12,4
//==>     Delay_ns(DS1302_CWH);
	ldi r24,lo8(2)
1:	dec r24
	brne 1b
	rjmp .
//==>     ds1302_setbyte(0x8e,0x80);                           // Reenable WP
	ldi r22,lo8(-128)
	ldi r24,lo8(-114)
/* epilogue start */
//==>   }
	pop r29
	pop r28
	pop r17
//==>     ds1302_setbyte(0x8e,0x80);                           // Reenable WP
	jmp ds1302_setbyte
	.size	ds1302_reset_time, .-ds1302_reset_time
.global	ds1302_clear
	.type	ds1302_clear, @function
ds1302_clear:
//==>   {
	push r28
/* prologue: function */
/* frame size = 0 */
/* stack size = 1 */
.L__stack_usage = 1
//==>     ds1302_reset_time();
	call ds1302_reset_time
//==>     ds1302_setbyte(0x8e,0x00);                           // Disable WP
	ldi r22,0
	ldi r24,lo8(-114)
	call ds1302_setbyte
//==>     CE_PORT|=_BV(CE_PIN);                                // Set CE high
	sbi 0x12,4
//==>     Delay_ns(DS1302_TCC);
	ldi r24,lo8(2)
1:	dec r24
	brne 1b
	rjmp .
//==>     ds1302_shiftout(0xfe);                               // Burst write RAM
	ldi r24,lo8(-2)
	call ds1302_shiftout
	ldi r28,lo8(28)
.L18:
//==>       ds1302_shiftout(0);
	ldi r24,0
	call ds1302_shiftout
	subi r28,lo8(-(-1))
//==>     for (c1=0;c1<28;c1++)                                // Set RAM to zeros
	brne .L18
//==>     ds1302_shiftout(SIG1);                               // Write signature to RAM
	ldi r24,lo8(-55)
	call ds1302_shiftout
//==>     ds1302_shiftout(SIG2);
	ldi r24,lo8(-7)
	call ds1302_shiftout
//==>     ds1302_shiftout(SIG3);
	ldi r24,lo8(49)
	call ds1302_shiftout
//==>     CE_PORT&=~_BV(CE_PIN);                               // Take CE back low
	cbi 0x12,4
//==>     Delay_ns(DS1302_CWH);
	ldi r24,lo8(2)
1:	dec r24
	brne 1b
	rjmp .
//==>     ds1302_setbyte(0x8e,0x80);                           // Reenable WP
	ldi r22,lo8(-128)
	ldi r24,lo8(-114)
/* epilogue start */
//==>   }
	pop r28
//==>     ds1302_setbyte(0x8e,0x80);                           // Reenable WP
	jmp ds1302_setbyte
	.size	ds1302_clear, .-ds1302_clear
.global	ds1302_init
	.type	ds1302_init, @function
ds1302_init:
//==>   {
	push r28
/* prologue: function */
/* frame size = 0 */
/* stack size = 1 */
.L__stack_usage = 1
//==>     CE_PORT&=~_BV(CE_PIN);                               // Default port configuration
	cbi 0x12,4
//==>     DDR(CE_PORT)|=_BV(CE_PIN);                           // CE output, low
	sbi 0x11,4
//==>     SCLK_PORT&=~_BV(SCLK_PIN);                           // SCLK output, low
	cbi 0x12,2
//==>     DDR(SCLK_PORT)|=_BV(SCLK_PIN);
	sbi 0x11,2
//==>     SIO_PORT&=~_BV(SIO_PIN);                             // SIO input, no pullup
	cbi 0x12,3
//==>     DDR(SIO_PORT)&=~_BV(SIO_PIN);
	cbi 0x11,3
//==>     c1=ds1302_getbyte(0x8f);                             // Test device presence (read WP byte)
	ldi r24,lo8(-113)
	call ds1302_getbyte
//==>     if (c1!=0x00 && c1!=0x80)                            // Result should always be 0x00 or 0x80
	mov r25,r24
	andi r25,lo8(127)
	breq .L21
.L23:
//==>       return 0;
	ldi r24,0
	rjmp .L22
.L21:
//==>     c1^=_BV(7);                                          // Flip bit and see if we can write/reread it
	ldi r28,lo8(-128)
	add r28,r24
//==>     ds1302_setbyte(0x8e,c1);
	mov r22,r28
	ldi r24,lo8(-114)
	call ds1302_setbyte
//==>     c2=ds1302_getbyte(0x8f);
	ldi r24,lo8(-113)
	call ds1302_getbyte
//==>     if (c1!=c2)                                          // New result should match written flipped bit
	cpse r28,r24
	rjmp .L23
//==>     if (!c2)
	cpse r28,__zero_reg__
	rjmp .L24
//==>       ds1302_setbyte(0x8e,0x80);                         // Leave WP set
	ldi r22,lo8(-128)
	ldi r24,lo8(-114)
	call ds1302_setbyte
.L24:
//==>     if (ds1302_getbyte(0xf9)!=SIG1 ||                    // Look for signature
	ldi r24,lo8(-7)
	call ds1302_getbyte
	cpi r24,lo8(-55)
	breq .L25
.L26:
//==>       ds1302_clear();                                    // Clear if no signature found
	call ds1302_clear
	rjmp .L27
.L25:
//==>         ds1302_getbyte(0xfb)!=SIG2 ||
	ldi r24,lo8(-5)
	call ds1302_getbyte
//==>     if (ds1302_getbyte(0xf9)!=SIG1 ||                    // Look for signature
	cpi r24,lo8(-7)
	brne .L26
//==>         ds1302_getbyte(0xfd)!=SIG3)
	ldi r24,lo8(-3)
	call ds1302_getbyte
//==>         ds1302_getbyte(0xfb)!=SIG2 ||
	cpi r24,lo8(49)
	brne .L26
.L27:
//==>     return 1;                                            // Device is present
	ldi r24,lo8(1)
.L22:
/* epilogue start */
//==>   }
	pop r28
	ret
	.size	ds1302_init, .-ds1302_init
.global	ds1302_get_time
	.type	ds1302_get_time, @function
ds1302_get_time:
//==>   {
	push r13
	push r14
	push r15
	push r16
	push r17
	push r28
	push r29
	in r28,__SP_L__
	in r29,__SP_H__
	sbiw r28,8
	in __tmp_reg__,__SREG__
	cli
	out __SP_H__,r29
	out __SREG__,__tmp_reg__
	out __SP_L__,r28
/* prologue: function */
/* frame size = 8 */
/* stack size = 15 */
.L__stack_usage = 15
	movw r16,r24
//==>     CE_PORT|=_BV(CE_PIN);                                // Set CE high
	sbi 0x12,4
//==>     Delay_ns(DS1302_TCC);
	ldi r18,lo8(2)
1:	dec r18
	brne 1b
	rjmp .
//==>     ds1302_shiftout(0xbf);                               // Burst read of time gets all registers in sync with each other
	ldi r24,lo8(-65)
	call ds1302_shiftout
	movw r24,r28
	adiw r24,1
	movw r14,r24
	ldi r24,lo8(8)
	mov r13,r24
	add r13,r14
.L29:
//==>       s1[c1]=ds1302_shiftin();
	call ds1302_shiftin
	movw r30,r14
	st Z+,r24
	movw r14,r30
//==>     for (c1=0;c1<8;c1++)
	cpse r13,r30
	rjmp .L29
//==>     CE_PORT&=~_BV(CE_PIN);                               // Take CE back low
	cbi 0x12,4
//==>     Delay_ns(DS1302_CWH);
	ldi r31,lo8(2)
1:	dec r31
	brne 1b
	rjmp .
//==>     if (s1[0] & _BV(7))                                  // If CH is set then clock is not set, return 0
	ldd r25,Y+1
	sbrc r25,7
	rjmp .L31
//==>     ATime->second=((s1[0] & (_BV(4)|_BV(5)|_BV(6)))>>4)*10         +(s1[0] & (_BV(0)|_BV(1)|_BV(2)|_BV(3)));
	mov r24,r25
	andi r24,lo8(112)
	lsr r24
	lsr r24
	lsr r24
	mov r18,r24
	lsl r18
	lsl r18
	add r24,r18
	andi r25,lo8(15)
	add r25,r24
	movw r30,r16
	std Z+5,r25
//==>     ATime->minute=((s1[1] & (_BV(4)|_BV(5)|_BV(6)))>>4)*10         +(s1[1] & (_BV(0)|_BV(1)|_BV(2)|_BV(3)));
	ldd r24,Y+2
	mov r25,r24
	andi r25,lo8(112)
	lsr r25
	lsr r25
	lsr r25
	mov r18,r25
	lsl r18
	lsl r18
	add r25,r18
	andi r24,lo8(15)
	add r24,r25
	std Z+4,r24
//==>     ATime->hour  =((s1[2] & (_BV(4)|_BV(5)))>>4)*10                +(s1[2] & (_BV(0)|_BV(1)|_BV(2)|_BV(3)));
	ldd r24,Y+3
	mov r25,r24
	andi r25,lo8(48)
	lsr r25
	lsr r25
	lsr r25
	mov r18,r25
	lsl r18
	lsl r18
	add r25,r18
	andi r24,lo8(15)
	add r24,r25
	std Z+3,r24
//==>     ATime->day   =((s1[3] & (_BV(4)|_BV(5)))>>4)*10                +(s1[3] & (_BV(0)|_BV(1)|_BV(2)|_BV(3)));
	ldd r24,Y+4
	mov r25,r24
	andi r25,lo8(48)
	lsr r25
	lsr r25
	lsr r25
	mov r18,r25
	lsl r18
	lsl r18
	add r25,r18
	andi r24,lo8(15)
	add r24,r25
	std Z+2,r24
//==>     ATime->month =((s1[4] & (_BV(4)))>>4)*10                       +(s1[4] & (_BV(0)|_BV(1)|_BV(2)|_BV(3)));
	ldd r24,Y+5
	bst r24,4
	clr r25
	bld r25,0
	lsl r25
	mov r18,r25
	lsl r18
	lsl r18
	add r25,r18
	andi r24,lo8(15)
	add r24,r25
	std Z+1,r24
//==>     ATime->year  =((s1[6] & (_BV(4)|_BV(5)|_BV(6)|_BV(7)))>>4)*10  +(s1[6] & (_BV(0)|_BV(1)|_BV(2)|_BV(3)));
	ldd r24,Y+7
	mov r25,r24
	swap r25
	andi r25,lo8(15)
	andi r24,lo8(15)
	ldi r31,lo8(10)
	mul r25,r31
	add r24,r0
	clr __zero_reg__
	movw r30,r16
	st Z,r24
//==>     return 1;
	ldi r24,lo8(1)
	rjmp .L30
.L31:
//==>       return 0;
	ldi r24,0
.L30:
/* epilogue start */
//==>   }
	adiw r28,8
	in __tmp_reg__,__SREG__
	cli
	out __SP_H__,r29
	out __SREG__,__tmp_reg__
	out __SP_L__,r28
	pop r29
	pop r28
	pop r17
	pop r16
	pop r15
	pop r14
	pop r13
	ret
	.size	ds1302_get_time, .-ds1302_get_time
.global	ds1302_set_time
	.type	ds1302_set_time, @function
ds1302_set_time:
//==>   {
	push r15
	push r16
	push r17
	push r28
	push r29
	in r28,__SP_L__
	in r29,__SP_H__
	sbiw r28,8
	in __tmp_reg__,__SREG__
	cli
	out __SP_H__,r29
	out __SREG__,__tmp_reg__
	out __SP_L__,r28
/* prologue: function */
/* frame size = 8 */
/* stack size = 13 */
.L__stack_usage = 13
	movw r30,r24
//==>     s1[0]=((ATime->second/10)<<4)+ATime->second%10;
	ldd r24,Z+5
	ldi r18,lo8(10)
	mov r22,r18
	call __udivmodqi4
	ldi r19,lo8(16)
	mul r24,r19
	add r25,r0
	clr __zero_reg__
	std Y+1,r25
//==>     s1[1]=((ATime->minute/10)<<4)+ATime->minute%10;
	ldd r24,Z+4
	call __udivmodqi4
	ldi r19,lo8(16)
	mul r24,r19
	add r25,r0
	clr __zero_reg__
	std Y+2,r25
//==>     s1[2]=((ATime->hour/10)<<4)  +ATime->hour%10;
	ldd r24,Z+3
	call __udivmodqi4
	ldi r19,lo8(16)
	mul r24,r19
	add r25,r0
	clr __zero_reg__
	std Y+3,r25
//==>     s1[3]=((ATime->day/10)<<4)   +ATime->day%10;
	ldd r24,Z+2
	call __udivmodqi4
	ldi r19,lo8(16)
	mul r24,r19
	add r25,r0
	clr __zero_reg__
	std Y+4,r25
//==>     s1[4]=((ATime->month/10)<<4) +ATime->month%10;
	ldd r24,Z+1
	call __udivmodqi4
	ldi r19,lo8(16)
	mul r24,r19
	add r25,r0
	clr __zero_reg__
	std Y+5,r25
//==>     s1[6]=((ATime->year/10)<<4)  +ATime->year%10;
	ld r24,Z
	call __udivmodqi4
	ldi r30,lo8(16)
	mul r24,r30
	add r25,r0
	clr __zero_reg__
	std Y+7,r25
//==>     s1[7]=0;
	std Y+8,__zero_reg__
//==>     ds1302_setbyte(0x8e,0x00);                           // Disable WP
	ldi r22,0
	ldi r24,lo8(-114)
	call ds1302_setbyte
//==>     CE_PORT|=_BV(CE_PIN);                                // Set CE high
	sbi 0x12,4
//==>     Delay_ns(DS1302_TCC);
	ldi r31,lo8(2)
1:	dec r31
	brne 1b
	rjmp .
//==>     ds1302_shiftout(0xbe);                               // Burst write of time sets all registers in sync with each other
	ldi r24,lo8(-66)
	call ds1302_shiftout
	movw r16,r28
	subi r16,-1
	sbci r17,-1
	ldi r24,lo8(8)
	mov r15,r24
	add r15,r16
.L34:
//==>       ds1302_shiftout(s1[c1]);
	movw r30,r16
	ld r24,Z+
	movw r16,r30
	call ds1302_shiftout
//==>     for (c1=0;c1<8;c1++)
	cpse r15,r16
	rjmp .L34
//==>     CE_PORT&=~_BV(CE_PIN);                               // Take CE back low
	cbi 0x12,4
//==>     Delay_ns(DS1302_CWH);
	ldi r31,lo8(2)
1:	dec r31
	brne 1b
	rjmp .
//==>     ds1302_setbyte(0x8e,0x80);                           // Reenable WP
	ldi r22,lo8(-128)
	ldi r24,lo8(-114)
/* epilogue start */
//==>   }
	adiw r28,8
	in __tmp_reg__,__SREG__
	cli
	out __SP_H__,r29
	out __SREG__,__tmp_reg__
	out __SP_L__,r28
	pop r29
	pop r28
	pop r17
	pop r16
	pop r15
//==>     ds1302_setbyte(0x8e,0x80);                           // Reenable WP
	jmp ds1302_setbyte
	.size	ds1302_set_time, .-ds1302_set_time
.global	ds1302_get_ram
	.type	ds1302_get_ram, @function
ds1302_get_ram:
//==>   {
/* prologue: function */
/* frame size = 0 */
/* stack size = 0 */
.L__stack_usage = 0
//==>     if (AAddress<28)
	cpi r24,lo8(28)
	brsh .L37
//==>       return ds1302_getbyte(0xc1+2*AAddress);
	lsl r24
	subi r24,lo8(-(-63))
	jmp ds1302_getbyte
.L37:
//==>   }
	ldi r24,0
	ret
	.size	ds1302_get_ram, .-ds1302_get_ram
.global	ds1302_set_ram
	.type	ds1302_set_ram, @function
ds1302_set_ram:
//==>   {
	push r28
	push r29
/* prologue: function */
/* frame size = 0 */
/* stack size = 2 */
.L__stack_usage = 2
//==>     if (AAddress<28)
	cpi r24,lo8(28)
	brsh .L38
	mov r29,r22
	mov r28,r24
//==>         ds1302_setbyte(0x8e,0x00);                           // Disable WP
	ldi r22,0
	ldi r24,lo8(-114)
	call ds1302_setbyte
//==>         ds1302_setbyte(0xc0+2*AAddress,AValue);              // Write
	mov r24,r28
	lsl r24
	mov r22,r29
	subi r24,lo8(-(-64))
	call ds1302_setbyte
//==>         ds1302_setbyte(0x8e,0x80);                           // Reenable WP
	ldi r22,lo8(-128)
	ldi r24,lo8(-114)
/* epilogue start */
//==>   }
	pop r29
	pop r28
//==>         ds1302_setbyte(0x8e,0x80);                           // Reenable WP
	jmp ds1302_setbyte
.L38:
/* epilogue start */
//==>   }
	pop r29
	pop r28
	ret
	.size	ds1302_set_ram, .-ds1302_set_ram
.global	ResetTime

	.section	.progmem.data,"a",@progbits
	.type	ResetTime, @object
	.size	ResetTime, 8
ResetTime:
	.byte	-128
	.byte	0
	.byte	0
	.byte	1
	.byte	1
	.byte	1
	.byte	0
	.byte	0
	.text
.Letext0:

That could be compiled immediately using GNU avr-as, it would need a little work to be used with Atmel Asm2.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Dear all,

 

I know you are all trying very hard indeed to help me.

 

I apologise if my intermittent attendance and misreading of the original comment about DS1302 vs DS1307 went completely over my head.

 

But with respect, for such experienced moderators (and this is my second life on this forum) you are committing two heinous sins that you always criticise beginners for.

 

First, you are not reading my postings fully. I have no issues with bit-bashing an interface - my issue was concern over using TWI/I2C, all I really needed to know was that it uses a serial interface with no complex addressing required, just a RST line which is actually a Chip Select by another name.

 

Second,  many suggestions were use a different part so you can hang it of another type of port. Nothing is worse than telling someone half way through a project 'if I was going there I wouldn't start from here' - at least not as long as their project isn't a complete write off.

 

 

As I don't have either USART or the SPI free and I would rather NOT have to use TWI) the DS1302 that I have got (with DS1302 written on it) is actually ideal for my needs as I planned in an expansion connector with five i/o ports and earth as a just in case - expecting to use it for flashing lights or similar.

 

Neil

 

P.S. in case it was overlooked, after my initial clumsy coding mistakes it turns out my problem is a broken pcb track on the CLK line.

It's me again...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Stub_Mandrel wrote:
misreading of the original comment about DS1302 vs DS1307 went completely over my head.

But at least three times between the two threads you said DS1203, leading to more doubt.  Then instead of simply answering the question to verify your part, you spent the time objecting to the question.

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Stub_Mandrel wrote:
for such experienced moderators (and this is my second life on this forum)

As far as I can see I am the only moderator who's contributed to this thread so are your comments directed to me?

 

The only post I've made here was, I hope, trying to be helpful. I understand there are still masochists who like to use just Asm (that is a JOKE by the way! ;-) and I was simply pointing out the utility of the -save-temps option hat can be passed to the avr-gcc compiler. It means "leave behind the usually hidden assembler source generated from the C". You can use this in one of two ways (a) your situation - you want some Asm code for something but can find nothing but C or (b) you're a C programmer but you aren't happy with the speed/efficiency of some section of the code that the compiler is generating.

 

In either case you can take the C, compile it with -save-temps. For any file.c in the source you now have a file.s that is "clean Asm". Now it may not be the greatest Asm in the world (C compilers have a nasty habit of using things like stack frames for local variables rather than pre-assigned "temp" registers" and stuff) so (in the case of GCC generated code anyway) you may see a lot of messing about with R29/R28 and indexing off Y+offset. You may choose to "improve" this to not use Y or the stack space. But the fact is that where you didn't have any Asm code to start with you now do. So I had hoped the suggestion might prove useful.

Last Edited: Thu. Apr 7, 2016 - 04:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I seem to be ruining people's lives.

 

I'll abandon this thread and perhaps start another one next time I get stuck.

 

Sorry.

 

Neil

It's me again...