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
@@ -97,6 +97,30 @@
|
||||
#define PORT_VIDEO 0x30
|
||||
#define PORT_VIDEO_TOP 0x3F
|
||||
|
||||
// ---- The timer ----
|
||||
//
|
||||
// The only regular beat this machine had was the screen finishing a frame, which is fixed at
|
||||
// sixty a second. That is a clock a program borrows rather than one it sets: every duration
|
||||
// becomes a multiple of 16.67 ms, so a note worth a third of a beat cannot be asked for and
|
||||
// the way round it is to choose a tempo whose subdivisions happen to land on whole frames -
|
||||
// which is making the music fit the hardware.
|
||||
#define PORT_TIMER 0x50
|
||||
#define PORT_TIMER_TOP 0x54
|
||||
|
||||
#define TIMER_STATUS 0x50
|
||||
#define TIMER_CONTROL 0x51
|
||||
#define TIMER_PERIOD_HIGH 0x52
|
||||
#define TIMER_PERIOD_MID 0x53
|
||||
#define TIMER_PERIOD_LOW 0x54
|
||||
|
||||
#define TIMER_STATUS_TICKED 0x01
|
||||
#define TIMER_STATUS_RUNNING 0x02
|
||||
#define TIMER_STATUS_INTERRUPT 0x04
|
||||
|
||||
#define TIMER_CONTROL_RUN 0x01
|
||||
#define TIMER_CONTROL_REPEAT 0x02
|
||||
#define TIMER_CONTROL_INTERRUPT 0x04
|
||||
|
||||
#define PORT_REGISTRY 0xFF
|
||||
|
||||
// ---- The console ----
|
||||
@@ -221,6 +245,7 @@ void consoleSetInputHook(int (*hook)(int mayWait));
|
||||
#define DEVICE_DISK 0x13
|
||||
#define DEVICE_VIDEO 0x14
|
||||
#define DEVICE_SOUND 0x15
|
||||
#define DEVICE_TIMER 0x16
|
||||
|
||||
// What a device brings besides itself. This means memory that somebody has to register
|
||||
// with the controller, so the controller's own bank 2 does not count: it is already there.
|
||||
@@ -382,6 +407,10 @@ void clearInterrupt(uint8_t port);
|
||||
// never asked the device for anything.
|
||||
void clearAllInterrupts(void);
|
||||
|
||||
// The timer, which counts the machine's own cycles.
|
||||
void timerReset(void);
|
||||
void timerTick(unsigned long now);
|
||||
|
||||
// The lowest numbered port with its line up, or -1 if none of them are.
|
||||
int nextPendingInterrupt(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user