A beat a program sets for itself
The only regular thing on this machine was the screen finishing a frame, sixty times a second and not negotiable - a clock a program BORROWS rather than one it sets. Every duration became a multiple of 16,667 cycles, so a sixteenth note at 120 beats a minute, which is 125,000, is seven and a half frames and cannot be asked for at all. The way round it was to choose a tempo whose subdivisions happen to land on whole frames, which is making the music fit the machine. Examples/tune.asm says so in its own header. 0x50 Status: a period went by, it is running, it will interrupt 0x51 Control: run, repeat, interrupt 0x52-0x54 The period, in cycles, most significant first THE PERIOD IS IN CYCLES because that is what everything else here is counted in - the cost model counts them and a frame is measured in them - so a timer counting anything else would be a second unit to remember. Twenty four bits reaches from one cycle to sixteen and a half seconds, with 120 beats a minute at 500,000 in the middle, and there is no range left for a prescaler to buy. Starting loads the period; asking it to run while it already is does not, so turning interrupts on half way through a period does not silently move the beat being kept. What is left over carries into the next period, so a period of 1,000 ticks every 1,000 and not every 1,000 plus however late anybody looked. Reading the status takes the tick down and the line with it, which is the rule this machine settled two days ago about every status port. The timing check is in terminal.sh and not the manifest, and the reason is worth keeping: settle() strips cycle counts from recordings, which is right for every other program and useless for a clock. "It printed eight dots" would pass on a timer that fired them all at once. terminal.sh measures that eight periods of 125,000 come to a million within a couple of hundred cycles, and that 99.97% of them were spent asleep. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
co-authored by
Claude Opus 5
parent
3e48e9690d
commit
6b51d6391f
@@ -0,0 +1,93 @@
|
||||
; A beat a program sets for itself.
|
||||
;
|
||||
; The only regular thing this machine had was the screen finishing a frame, sixty times a
|
||||
; second and not negotiable. That is a clock a program BORROWS: every duration becomes a
|
||||
; multiple of 16.67 ms, so a sixteenth note at 120 beats a minute - 125,000 cycles, which is
|
||||
; seven and a half frames - cannot be asked for at all.
|
||||
;
|
||||
; Counted in cycles, because that is what everything else on this machine is counted in.
|
||||
;
|
||||
; Written by Anachronaut
|
||||
|
||||
#Program
|
||||
|
||||
start:
|
||||
; ---- Repeating, and polled ----
|
||||
;
|
||||
; 100,000 cycles, a tenth of a second. Four of them, so the whole thing is 400,000 and the
|
||||
; recorded cycle count is the check that the period is what it says.
|
||||
INIA 0x01
|
||||
OUTA 0x52
|
||||
INIA 0x86
|
||||
OUTA 0x53
|
||||
INIA 0xA0
|
||||
OUTA 0x54 ; 0x0186A0
|
||||
|
||||
INIA 0x03
|
||||
OUTA 0x51 ; Run, repeat, no interrupt.
|
||||
|
||||
INIB 0d4
|
||||
everyTick:
|
||||
INA 0x50
|
||||
PSHB
|
||||
INIB 0x01
|
||||
AND
|
||||
POPB
|
||||
BRQ everyTick ; Not yet.
|
||||
INIA 0d46
|
||||
OUTA 0x00
|
||||
DECB
|
||||
BNB everyTick
|
||||
|
||||
; ---- And looking is what answered it ----
|
||||
;
|
||||
; The bit came down when it was read, so asking again immediately says nothing has happened
|
||||
; since. A timer whose flag stayed up would look like a beat every time round the loop.
|
||||
INA 0x50
|
||||
INIB 0x01
|
||||
AND
|
||||
BRQ tickCleared
|
||||
INIA 0d78 ; 'N'
|
||||
OUTA 0x00
|
||||
BRI oneShot
|
||||
tickCleared:
|
||||
INIA 0d89 ; 'Y'
|
||||
OUTA 0x00
|
||||
|
||||
oneShot:
|
||||
; ---- Once, and then stopped ----
|
||||
;
|
||||
; Without the repeat bit it runs its period out and turns itself off, which the status port
|
||||
; says: bit 1 is whether it is running.
|
||||
RSTA
|
||||
OUTA 0x51 ; Stop first, so starting below is a start.
|
||||
INIA 0x01
|
||||
OUTA 0x51 ; Run, no repeat.
|
||||
|
||||
waitOnce:
|
||||
INA 0x50
|
||||
INIB 0x01
|
||||
AND
|
||||
BRQ waitOnce
|
||||
INIA 0d46
|
||||
OUTA 0x00
|
||||
|
||||
INA 0x50
|
||||
INIB 0x02 ; RUNNING
|
||||
AND
|
||||
BRQ stopped
|
||||
INIA 0d78
|
||||
OUTA 0x00
|
||||
BRI done
|
||||
stopped:
|
||||
INIA 0d89
|
||||
OUTA 0x00
|
||||
|
||||
done:
|
||||
INIA 0d10
|
||||
OUTA 0x00
|
||||
HALT
|
||||
|
||||
#Vectors
|
||||
|
||||
Boot start
|
||||
Reference in New Issue
Block a user