Clock device

This is the user manual for the clock device of the Bedrock computer system.

This document is aimed at people who are learning about or writing programs for the Bedrock system. For people who are implementing the system from scratch, the clock device specification will provide more relevant information.

Overview

The clock device provides access to a real-time clock and four countdown timers.

Concepts

Durations for the uptime and timer ports are represented as doubles, with the unit being 1/256 of a second. This has the consequence that the upper byte of a duration represents whole seconds, and the lower byte represents fractions of a second. The maximum representable duration is just under 4 minutes and 17 seconds.

Ports

Port Name Description Read Write
30 Year Current year.
31 Month Current month of the year.
32 Day Current day of the month.
33 Hour Current hour of the day.
34 Minute Current minute of the hour.
35 Second Current second of the minute.
36 Uptime Incrementing counter.
37 grouped grouped
38 Timer Countdown timer 1.
39 grouped grouped
3A Timer Countdown timer 2.
3B grouped grouped
3C Timer Countdown timer 3.
3D grouped grouped
3E Timer Countdown timer 4.
3F grouped grouped

Year

Reading a byte from this port will return the current year as a number since the year 2000. The year 2025 would be returned as 25, or 19 in hexadecimal.

Writing to this port will set the year if the system supports it.

Byte Year Byte Year Byte Year
00 2000 0A 2010 14 2020
01 2001 0B 2011 15 2021
02 2002 0C 2012 16 2022
03 2003 0D 2013 17 2023
04 2004 0E 2014 18 2024
05 2005 0F 2015 19 2025
06 2006 10 2016 1A 2026
07 2007 11 2017 1B 2027
08 2008 12 2018 1C 2028
09 2009 13 2019 1D 2029

Month

Reading a byte from this port will return the current month, with 00 being January and 0B being December.

Writing to this port will set the month if the system supports it.

Byte Month name Byte Month name
00 January 06 July
01 February 07 August
02 March 08 September
03 April 09 October
04 May 0A November
05 June 0B December

Day

Reading a byte from this port will return the current day of the month, with 00 being the 1st of the month and 1E being the 31st.

Writing to this port will set the day if the system supports it.

Hour

Reading a byte from this port will return the current hour, with 00 being 12 o’clock midnight and 17 being 11 o’clock at night.

Writing to this port will set the hour if the system supports it.

Minute

Reading a byte from this port will return the current minute, with 00 being zero minutes past the hour and 3B being 59 minutes past the hour.

Writing to this port will set the minute if the system supports it.

Second

Reading a byte from this port will return the current second, with 00 being zero seconds past the minute and 3B being 59 seconds past the minute.

Writing to this port will set the second if the system supports it.

Uptime

Reading a double from this port will return the time elapsed since the Bedrock system was started, measured in 1/256 increments. The value will wrap around to zero on overflow.

See the frame delta example.

Timer

Each of the four timer ports provides access to one of the four countdown timers. Each timer is a double value that decrements every 1/256 second, waking the system when it reaches zero.

Writing a double to one of these ports will set the value of that timer, and reading a double will return the current value.

See the setting a timer example.

Wake behaviour

This device will wake the system from sleep when any of the four timers reach zero.

Examples

Frame delta

To get the duration elapsed since the previous frame, we can store the uptime value during the previous frame and subtract it from the uptime this frame. This example sleeps for a random duration and then prints the frame delta:

@main
  JMS:get-delta               ( delta*     )
  DUP* JMS:print-double       (            )
  ROL*:05 XOR SWP:00 SHL*:01  ( timer*     )
  STD*:38 *:1000 STD*:00      (            )
  JMP:main

@get-delta  ( -- d* )
  LDD*:36 *:[&prev 0000]      ( new* old*  )
  OVR* STA*:~prev SUB*        ( delta*     )
  JMPr

@print-double  ( n* -- )
  r:04 &loop                  ( n*     | i )
    ROL*:04 DUP AND:0F        ( n* d   | i )
    DUP GTH:09 AND:07         ( n* d l | i )
    ADD ADD:30 STD:86         ( n*     | i )
    DECr DUPr JCNr:~loop      ( n*     | i )
  POPr POP* :00 STD:83        (        |   )
  JMPr                        (        |   )

Setting a timer

The upper byte of a timer value represents a number of whole seconds, and the lower byte represents fractions of a second:

@start
  LDD*:38 JCN*:{    ( if timer 1 has expired:      )
    :'|' STD:86     (   print a '|' character      )
    *:0100 STD*:38  (   set timer 1 to 1 second    )
  }
  LDD*:3A JCN*:{    ( if timer 2 has expired:      )
    :'.' STD:86     (   print a '.' character      )
    *:0040 STD*:3A  (   set timer 2 to 1/4 second  )
  }
  *:1000 STD*:00    ( wait for a clock event       )
  JMP:start         ( return to the start          )