Den lilla haken är bara den att frekvenen som står stämplad på kristallen är
ju ett börvärde, ärvärdet brukar aldrig vara exakt nog för att användas som
tidbas i en klocka. Frekvensen blir udda om man inte kalibrerar i hårdvara.
Eftersom det är svårt och kräver en räknare med jättefin tidbas så är det
för en amatör bättre att kalibrera i mjukvara. Då går det att räkna fram den
nya delaren utifrån vetskap om den gamla och det fel den producerar över en
längre tidsperiod. Därigenom kan man få exakt kalibrering utan den fina
räknaren med rubidiumnormal, det räcker med klockan i TV och en
"gatetime" på en dag, vecka eller månad eller kanske ännu längre allt efter
som noggrannheten närmar sig det rätta värdet.
Det är så enkelt att implementera en breesenham-delare i mjukvara att jag
ser ingen anledning att låta bli. Tekniken är helt enkelt för dåligt känd, det
är antagligen orsaken till att inte fler använder den. Fördelen är enorm att
kunnaställa en delare på t.ex. 8.586925814 istället för bara heltal.
Med 4 bytes, heltal plus tre deltal, så kan man ställa delaren i steg på
1/16777216-delar och det räcker för alla normal kristaller. Det enda som
behöver göras är 4 stycken 1-bytes add with carry. Svårare är det inte.
Här är assemblerkod, inklusive variabeldefinitioner.
Kod: Markera allt
BCNTER * BREESENHAM COUNTER FOR SECONDS TICK
.0CNT .BS 1 WHOLE NUMBERS
.1CNT .BS 1 FIRST FRACTION, 1/256
.2CNT .BS 1 SECOND FRACTION, 1/65536
.3CNT .BS 1 THIRD FRACTION, 1/16.777.216
.0LOAD .EQ EESAVE.B0LOAD WHOLE NUMBERS RELOAD
.1LOAD .EQ EESAVE.B1LOAD FIRST FRACTION RELOAD
.2LOAD .EQ EESAVE.B2LOAD SECOND FRACTION RELOAD
.3LOAD .EQ EESAVE.B3LOAD THIRD FRACTION RELOAD
* NOMINAL DIVIDER IS 9.536 743 164
.0DFALT .EQ 9 WHOLE NUMBERS DEFAULT
.1DFALT .EQ 137 FIRST FRACTION DEFAULT
.2DFALT .EQ 104 SECOND FRACTION DEFAULT
.3DFALT .EQ 0 THIRD FRACTION DEFAULT
DOTIME * DO BREESENHAM DOUNTER
DSZ BCNTER.0CNT COUNT DOWN WHOLE NUMBER
RTS NO COUNTOUT-DONE
* RELOAD BY ADDING IN FRACTIONAL COUNT VALUE
LOD A,BCNTER.3LOAD GET 3:RD FRACTION
ADD BCNTER.3CNT,A ADD IT IN
LOD A,BCNTER.2LOAD GET 2:ND FRACTION
SFC CY WAS THERE A CARRY?
ISZ A=BCNTER.2LOAD YES-GET VALUE INCREMENTED BY ONE
ADD BCNTER.2CNT,A ADD IN, BUT ONLY IF NO NEW CARRY-OVER
LOD A,BCNTER.1LOAD GET 1:ST FRACTION
SFC CY WAS THERE A CARRY?
ISZ A=BCNTER.1LOAD YES-GET VALUE INCREMENTED BY ONE
ADD BCNTER.1CNT,A ADD IN, BUT ONLY IF NO NEW CARRY-OVER
LOD A,BCNTER.0LOAD GET WHOLE NUMBER
SFC CY WAS THERE A CARRY?
ISZ A=BCNTER.0LOAD YES-GET VALUE INCREMENTED BY ONE
ADD BCNTER.0CNT,A ADD IN, BUT ONLY IF NO NEW CARRY-OVER
* A SECOND HAS ELAPSED, COUNT UP TIMEKEEPING