Hack to preserve date/time across a reset of the ZBasic VM

Here you can share completed projects or parts of projects that may be useful to others. You may post files relevant to ZBasic - source code, schematics, etc.
Post Reply
stevech
Posts: 715
Joined: 22 February 2006, 20:56 PM

Hack to preserve date/time across a reset of the ZBasic VM

Post by stevech »

This code preserves the date and time within the ZBasic VM operating system across a reset or re-download of a a new program. Often, the chip gets reset by DTR toggling merely due to opening a serial port on the PC to see the console output.

The time it took to reset (a second or two, or the time to dowload (a few seconds), is lost, but this is better than nothing! A clock chip would be nice too, but nada. The code won't deal with a power-off/on of course, and you can make a choice on not retrieving date/time from RAM based on the system register for "cause of reset".

This code is a bit of a hack. It saves the date/time to RAM once a second (you can change that rate), in an area of RAM unlikely to be erased during the reset. This could change due to VM changes, but for now, it works. This RAM area is at a higher address than the maximum expected address for the main() tasks's stack, and lower than the heap is expected to go. With the larger RAM on the AVR 644 chip as is the ZX24a et al, this is less of a risk.

In another posting here today, I showed a program to set the date/time in the VM by parsing out incoming serial data created by a MS Windows command line echo date time command.

Don may have a suggestion on a tweak. This is my first attempt at based variables so beware.

It would be kinda nice to have a compiler option to set the base address of static variables to something above 0, so this secret stash area could be assuredly preserved.

Here's the code to put in the heading and in main()

Code: Select all

const RAMstashOffset as unsignedInteger = 300 ' offset from stack pointer of main() to unused RAM we hope
private saveDateTimeToRAMstack(40)	as byte
...
main()
...
userSPmain = register.userSP ' save in a global
callTask saveDateTimeToRAM, saveDateTimeToRAMstack

sub saveDateTimeToRAM() ' a task
	Dim RAMaddr	as UnsignedInteger
	Dim mm as byte 	Based (RAMaddr+0)
	Dim d as byte 		Based (mm.dataAddress+sizeof(byte))
	Dim y as integer 	Based (d.dataAddress+sizeof(byte))
	Dim h as byte 		Based (y.dataAddress+sizeof(integer))
	Dim m as byte 		Based (h.dataAddress+sizeof(byte))
	Dim secs as single 	Based (m.dataAddress+sizeof(byte))

	RAMaddr = userSPmain + RAMstashOffset
	'debug.print "RAMaddr:";cstr(RAMaddr);" secs addr ";cstr(secs.dataAddress)
	call PutTimeStamp(y, mm, d, h, m, secs) ' set the date/time from what was saved
	console.writeline( "date/time recalled from RAM")
	
	do
		call getTimeStamp(y, mm, d, h, m, secs)	' put time into RAM storage
		sleep(1.0)
	loop
end sub
dkinzer
Site Admin
Posts: 3120
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

Using a structure might simplify the code:

Code: Select all

sub saveDateTimeToRAM() ' a task 
	Structure TimeDate
		Dim mm as Byte
		Dim d as Byte
		Dim y as Integer
		Dim h as Byte
		Dim m as Byte
		Dim secs as Single
	End Structure
   Dim RAMaddr   as UnsignedInteger 
   Dim td as TimeDate Based (RAMaddr+0)

   RAMaddr = userSPmain + RAMstashOffset 
   'debug.print "RAMaddr:";cstr(RAMaddr);" secs addr ";cstr(secs.dataAddress) 
   call PutTimeStamp(td.y, td.mm, td.d, td.h, td.m, td.secs) ' set the date/time from what was saved 
   console.writeline( "date/time recalled from RAM") 
    
   do 
      call getTimeStamp(td.y, td.mm, td.d, td.h, td.m, td.secs)   ' put time into RAM storage 
      sleep(1.0) 
   loop 
end sub
- Don Kinzer
stevech
Posts: 715
Joined: 22 February 2006, 20:56 PM

Post by stevech »

yes - I used such structures in the DS1820 code uploaded some time ago.
Here, I used individual variables, as I was curious if all the address math at run time would be as I thought.
Post Reply