In this thread discussions about the ZX81 Nixie Clock source code. It is open source, so everyone can have a look at it and make modifications where possible. Would be nice to have a DCF77 interface connected to it, as found in the German forum. It wouldn't be of any help to me as we can't receive the signal in Australia, in fact, the only possible solution here would be through a GPS system . To keep the clock accurate without a radio reference, I have implemented 6 calibration registers. The main register is 24 bits, the others are 16 bits. The values for these registers can be calculated using the BASIC program CALCLC7.P (also added in attached file). It basically calculates when a clock tick needs to be added or subtracted from the event stream. There are normally 50 or 60 ticks coming in per second, this is however not accurate at all. If you were just counting these ticks, the clock will run 7 seconds fast per 10 minutes on a 50Hz Zeddy and 9 seconds slow per 30 minutes on a 60Hz zeddy. The main calibration register roughly corrects this to an accuracy of about 5 seconds/day. The other 5 sub registers can adjust this further down to about 1.5 sec per year. However, with a normal ceramic resonator (6.5MHz) you probably won't get a better result than 1 second per day, if you change this resonator to a quartz crystal you probably get to 2 seconds per month and with a TCXO you should be able to get to 1.5 sec/year. So although the calibration routines are too complicated for most Zeddies, if you really want to, you can make a very accurate clock using this software.
Calibration is done in steps, you first measure the deviation in say 30 minutes. Fill out the data in the CALCLC7 program, enter the calibration data into the assembly file, then assemble the file using ZX-IDE, transfer the file and let the clock run for say 1 day. Measure the deviation, fill it out in the CALCLC7 program etc etc. After 2 or 3 times (say 30 minutes, then 1 day, then 1 week) you have a very accurate clock.
http://xiac.com/ZX81/ZX81NixieClock.zip
Suggestions welcome.
Michel
ZX81 Nixie Clock Source code
Re: ZX81 Nixie Clock Source code
Well took a look at your source but it's a bit complicate.
Just three suggestions from my side:
1. You can use the variables section (printer buffer) directly when you include ZX81VARS.INC (and ZX81DEF.INC) instead of simply ZX81.INC
Then you can skip the copy of variables from BASIC line 10.
But you do this several times in your source - don't know why.
2. You can write directly into the display file and you can fill the display file with your 8 characters easily.
Just write directly into the display buffer instead of calling ROM functions.
3. I think the adjustment can be made more easily when you find out how many seconds the clock is running if one second deviation (by running clock for maybe 24 hours) and determine to add od subtract a second every 12533 seconds (if this is the deviation).
So the trick is to keep it more simple.
But your clock is a great gadget for the ZX81 - I have all respect for your development. Just a few hints when overflowing your code.
Just three suggestions from my side:
1. You can use the variables section (printer buffer) directly when you include ZX81VARS.INC (and ZX81DEF.INC) instead of simply ZX81.INC
Then you can skip the copy of variables from BASIC line 10.
But you do this several times in your source - don't know why.
Code: Select all
CLOCK_PORT EQU $3F ;EITHER $3F OR $77
SCROLL_CNT EQU 19
; content of ZX81VARS.INC modified (variable section)
virtual at MEMST
ERR_NR db ? ; error number $ff is no error
FLAGS db ? ; flags of system
ERR_SP dw ? ; first item of machine stack
RAMTOP dw ? ; top address of ram, first non-existing memory location
MODE db ? ; cursor mode (K/L,F,G)
PPC dw ? ; line number currently executed
SAVE_BEGIN: ; start address of prgrams loaded into memory
end virtual
ORG SAVE_BEGIN
VERSN db 0 ; version, 0=ZX81 BASIC
E_PPC dw 0 ; number of current line with cursor (in listing)
D_FILE dw DFILE_ADDR ; begin of D_FILE (display file) in memory
DF_CC dw DFILE_ADDR+1 ; current cursor position in D_FILE (used for print routine)
VARS dw VARS_ADDR ; begin of variable section in memory
DEST dw 0 ; address of variable in assignment
E_LINE dw WORKSPACE ; address of workspace
if defined AUTORUN
CH_ADD dw AUTORUN ; address of next character to be interpreted
else
CH_ADD dw 0 ; address of next character to be interpreted
end if
X_PTR dw 0 ; address of character preceeding "S" marker
STKBOT dw WORKSPACE ; stack botton (top-down)
STKEND dw WORKSPACE ; end of stack (top)
BERG db 0 ; calculators b register, possibly write error, should be BREG :-)
MEM dw MEMBOT ; address for calculator's memory
UNUSED1 db 0 ; unused variable / space
DF_SZ db 2 ; no. of lines in lower part of screen including 1 blank line
S_TOP dw 0 ; no. of top program line in automatic listings
LAST_K dw 0 ; last key pressed
DEBOUNCE db 0 ; debounce status of keyboard
MARGIN db PAL ; margin value, could be used PAL or NTSC
if defined AUTORUN
NXTLIN dw AUTORUN ; next line to be executed
else
NXTLIN dw 0 ; next line to be executed
end if
OLDPPC dw 0 ; line to jump when executing CONT (continue)
FLAGX db 0 ; internal flags
STRLEN dw 0 ; length of string, interally used
T_ADDR dw 0 ; next item in syntax (token) table
SEED dw 0 ; seed variable set by RAND
FRAMES dw 0 ; counter of frames sent to TV, used by PAUSE command
COORDS db 0 ; x coordinate of last point plotted
db 0 ; y coordinate of last point plotted
PR_CC db $BC ; LPRINT position used with real printer
S_POSN db 33 ; column no. for print position
db 24 ; line no. for print position
if defined FASTMODE
CDFLAG db FAST_MODE ; compute and display flag
else
CDFLAG db SLOW_MODE
end if
begin_of_printer_buffer: ;($403C)
hours db 0; equ $403c ;printer buffer area
mints db 0; equ $403d ;
secnd db 0; equ $403e ;
dummy db 0; equ $403f ;
pscale1 db 0; equ $4040 ;2Hz pre-scaler
correct db 0; equ $4041 ;correction register to add or substract events (calibration)
psth db 0; equ $4042 ;pre-scaler threshold level; dependent on 50Hz or 60Hz
regcntr db 0; equ $4043 ;used in the update calibration routine to count the processed amount of registers
cflgs db 3 dup(0) ; equ $4044 ;
cal1r db 90,0,0 ; equ $4047 ;
cal2r db 0,0 ; equ $404a ;
cal3r db 0,0 ; equ $404c ;
cal4r db 0,0 ; equ $404e ;
cal5r db 0,0 ; equ $4050 ;
cal6r db 0,0 ; equ $4052 ;
csign db 0 ; sign for correction (either positive (0-slow down) or negative (1-speed up))
;0 for 50Hz/PAL; 1 for 60Hz/NTSC
scroll db 0 ; equ $4054
rotcnt db SCROLL_CNT ; equ $4055
resprbuf db 6 dup(0)
MEMBOT db 30 dup(0) ; calculator additional memory ???
UNUSED2 dw 0 ; unused variable / space
BASIC_AREA:
Code: Select all
DFILE_ADDR:
db 25 dup(NEWLINE)
instead write:
db NEWLINE ; sync of picture
dbzx '********',NEWLINE ; first line
db 23 dup (NEWLINE) ; following lines
3. I think the adjustment can be made more easily when you find out how many seconds the clock is running if one second deviation (by running clock for maybe 24 hours) and determine to add od subtract a second every 12533 seconds (if this is the deviation).
So the trick is to keep it more simple.
But your clock is a great gadget for the ZX81 - I have all respect for your development. Just a few hints when overflowing your code.
Re: ZX81 Nixie Clock Source code
Hi PokeMon, Thanks for having a look at the code.
>>>Well took a look at your source but it's a bit complicate.
Just three suggestions from my side:
1. You can use the variables section (printer buffer) directly when you include ZX81VARS.INC (and ZX81DEF.INC) instead of simply ZX81.INC
Then you can skip the copy of variables from BASIC line 10.
OK, that sounds like a plan. Yes, sure I need to copy this several times because 1 set is the set values and the other registers count down to 0 and need to be re-loaded once they reach 0.
2. You can write directly into the display file and you can fill the display file with your 8 characters easily.
That's what I had done initially, but the problem is when I return to basic, I loose these characters and so cannot run the program anymore without messing up the screen . That's why I print them in the code so that every time when I type RUN, the characters will be printed to the screen and I know the display memory is there.
3. I think the adjustment can be made more easily when you find out how many seconds the clock is running if one second deviation (by running clock for maybe 24 hours) and determine to add od subtract a second every 12533 seconds (if this is the deviation).
...... that is a dirty trick..... no clock builder will respect that . However, even that is not as simple as you think because adding/subtracting seconds means you need to check minutes for overflow, check hours for overflow and you need to define somehow when these seconds need to be added/subtracted. Once you program that, you will probably come to the conclusion that skipping clock ticks is the best and simplest way to go.
Michel
>>>Well took a look at your source but it's a bit complicate.
Just three suggestions from my side:
1. You can use the variables section (printer buffer) directly when you include ZX81VARS.INC (and ZX81DEF.INC) instead of simply ZX81.INC
Then you can skip the copy of variables from BASIC line 10.
OK, that sounds like a plan. Yes, sure I need to copy this several times because 1 set is the set values and the other registers count down to 0 and need to be re-loaded once they reach 0.
2. You can write directly into the display file and you can fill the display file with your 8 characters easily.
That's what I had done initially, but the problem is when I return to basic, I loose these characters and so cannot run the program anymore without messing up the screen . That's why I print them in the code so that every time when I type RUN, the characters will be printed to the screen and I know the display memory is there.
3. I think the adjustment can be made more easily when you find out how many seconds the clock is running if one second deviation (by running clock for maybe 24 hours) and determine to add od subtract a second every 12533 seconds (if this is the deviation).
...... that is a dirty trick..... no clock builder will respect that . However, even that is not as simple as you think because adding/subtracting seconds means you need to check minutes for overflow, check hours for overflow and you need to define somehow when these seconds need to be added/subtracted. Once you program that, you will probably come to the conclusion that skipping clock ticks is the best and simplest way to go.
Michel