summaryrefslogtreecommitdiff
path: root/chapter31/docs/examples/Clock.smp
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-11-13 13:10:15 -0800
committerCliff Click <cliffc@acm.org>2026-11-13 13:10:15 -0800
commit299addd03094389bb622e0fe1d7ad585b51e146d (patch)
treefde1f3d0d440665428786c8bc35bd9d037034e2c /chapter31/docs/examples/Clock.smp
parentb7440c1e4c182ad977996d91bfb8125091ffae92 (diff)
downloadSimple-299addd03094389bb622e0fe1d7ad585b51e146d.tar.gz
Simple-299addd03094389bb622e0fe1d7ad585b51e146d.zip
Cleanp the new time & graphics APIs
Diffstat (limited to 'chapter31/docs/examples/Clock.smp')
-rw-r--r--chapter31/docs/examples/Clock.smp76
1 files changed, 44 insertions, 32 deletions
diff --git a/chapter31/docs/examples/Clock.smp b/chapter31/docs/examples/Clock.smp
index 900126e1..2dea18ec 100644
--- a/chapter31/docs/examples/Clock.smp
+++ b/chapter31/docs/examples/Clock.smp
@@ -1,50 +1,61 @@
// Local clocks; click the button or press Space to switch. Q/Escape exits.
// Any argument runs ten frames, exercising both faces for smoke tests.
u32 GREEN=0x62ff70, DIM=0x123d20, BACKGROUND=0x020b05;
+
val main = { u8[~][] args ->
- val screen=new sys.draw.Canvas(720,540);
+ // The main Canvas
+ val screen = new sys.draw.Canvas(720,540);
if( sys.gfx.open("Simple digital and analog clocks",screen.width,screen.height)!=sys.gfx.OK ) return 1;
- val button=new sys.draw.Button(220,454,280,52,"ANALOG CLOCK");
- val timers=new sys.time.Timers();
- i64 frame=timers.every(33);
- if( frame<0 ) { sys.gfx.close(); return 1; }
+
+ // Button to flip clock style
+ val button = new sys.draw.Button(220,454,280,52,"ANALOG CLOCK");
+ val timers = new sys.time.Timers();
+ u32 frame_id = timers.every(33);
+ if( frame_id==0 ) { sys.gfx.close(); return 1; }
+
bool analog=false, held=false;
int frames=0, status=sys.gfx.OK;
+
+ // Main event loop
while( status==sys.gfx.OK ) {
- bool space=sys.gfx.key(' ');
- bool down=sys.gfx.button(sys.gfx.LEFT);
- bool click=button.update(sys.gfx.mouseX(),sys.gfx.mouseY(),down);
+ bool space = sys.gfx.key(' ');
+ bool down = sys.gfx.button(sys.gfx.LEFT);
+ bool click = button.update(sys.gfx.mouseX(),sys.gfx.mouseY(),down);
if( click || (space && !held) ) analog=!analog;
- held=space;
- button.label=analog ? "DIGITAL CLOCK" : "ANALOG CLOCK";
+ held = space;
+ button.label = analog ? "DIGITAL CLOCK" : "ANALOG CLOCK";
if( sys.gfx.key('Q') ) break;
- if( timers.poll(sys.time.monotonic())==frame ) {
+ if( timers.poll(sys.time.monotonic())==frame_id ) {
_draw(screen,sys.time.now(),analog);
button.draw(screen,3,GREEN,BACKGROUND,DIM);
- status=sys.gfx.present(screen.pixels);
+ status = sys.gfx.present(screen.pixels);
if( args#>1 ) {
frames++;
if( frames==5 ) analog=true;
if( frames==10 ) break;
}
}
- if( status==sys.gfx.OK ) status=sys.gfx.wait(sys.time.remaining(timers.nextDeadline(),sys.time.monotonic()));
+ if( status!=sys.gfx.OK ) break;
+ // Stall until next timer event
+ status = sys.gfx.wait(sys.time.remaining(timers.nextDeadline(),sys.time.monotonic()));
}
sys.gfx.close();
return status==sys.gfx.ERROR ? 1 : 0;
};
-val _draw = { !sys.draw.Canvas screen, i64 wall, i64 analog ->
- val d=sys.time.local(wall);
+
+val _draw = { !sys.draw.Canvas screen, i64 wall_ms, i64 analog ->
+ val d = sys.time.local(wall_ms);
screen.clear(BACKGROUND);
screen.text(266,24,"SIMPLE CLOCK",4,GREEN);
- if( analog ) _analog_noInline(screen,d.hour,d.minute,d.second,d.millisecond);
- else _digital_noInline(screen,d.hour,d.minute,d.second);
- screen.text(298,412,"%(sys.time.formatLocal(wall,sys.time.DATE))",4,GREEN);
+ if( analog ) _analog(screen,d.hour,d.minute,d.second,d.millisecond);
+ else _digital(screen,d.hour,d.minute,d.second);
+ screen.text(298,412,"%(sys.time.formatLocal(wall_ms,sys.time.DATE))",4,GREEN);
screen.text(249,520,"SPACE SWITCH Q OR ESC QUIT",2,GREEN);
};
+
// a..g bits: top, upper-right, lower-right, bottom, lower-left, upper-left,
// middle. Faint unlit bars retain the old LED figure-eight silhouette.
-val _digit_noInline = { !sys.draw.Canvas c, int x, int y, i64 digit ->
+val _digit = { !sys.draw.Canvas c, int x, int y, i64 digit ->
int bits=digit==0 ? 0x3f : digit==1 ? 0x06 : digit==2 ? 0x5b :
digit==3 ? 0x4f : digit==4 ? 0x66 : digit==5 ? 0x6d :
digit==6 ? 0x7d : digit==7 ? 0x07 : digit==8 ? 0x7f : digit==9 ? 0x6f : 0;
@@ -60,10 +71,11 @@ val _digit_noInline = { !sys.draw.Canvas c, int x, int y, i64 digit ->
}
}
};
-val _digital_noInline = { !sys.draw.Canvas c, int hour, int minute, int second ->
- _digit_noInline(c,68,166,hour/10); _digit_noInline(c,154,166,hour-hour/10*10);
- _digit_noInline(c,284,166,minute/10); _digit_noInline(c,370,166,minute-minute/10*10);
- _digit_noInline(c,500,166,second/10); _digit_noInline(c,586,166,second-second/10*10);
+
+val _digital = { !sys.draw.Canvas c, int hour, int minute, int second ->
+ _digit(c,68,166,hour/10); _digit(c,154,166,hour-hour/10*10);
+ _digit(c,284,166,minute/10); _digit(c,370,166,minute-minute/10*10);
+ _digit(c,500,166,second/10); _digit(c,586,166,second-second/10*10);
for( int i=0; i<2; i++ ) {
c.fillCircle(254+i*216,214,6,GREEN);
c.fillCircle(254+i*216,262,6,GREEN);
@@ -72,7 +84,7 @@ val _digital_noInline = { !sys.draw.Canvas c, int hour, int minute, int second -
};
// Rational sine approximation, accurate enough for pixel clock geometry.
// Arguments are nonnegative turns; no additional native math dependency.
-val _sin_noInline = { f64 turn ->
+val _sin = { f64 turn ->
i64 whole=turn; turn-=whole;
bool negative=turn>0.5;
f64 x=(negative ? turn-0.5 : turn)*6.283185307179586;
@@ -80,26 +92,26 @@ val _sin_noInline = { f64 turn ->
f64 numerator=negative ? -16.0 : 16.0;
return numerator*product/(49.34802200544679-4*product);
};
-val _hand_noInline = { !sys.draw.Canvas c, f64 turn, int length, int thickness, u32 color ->
- int x=360+_sin_noInline(turn)*length, y=232-_sin_noInline(turn+0.25)*length;
+val _hand = { !sys.draw.Canvas c, f64 turn, int length, int thickness, u32 color ->
+ int x=360+_sin(turn)*length, y=232-_sin(turn+0.25)*length;
c.line(360,232,x,y,thickness,color);
};
-val _analog_noInline = { !sys.draw.Canvas c, int hour, int minute, int second, int millisecond ->
+val _analog = { !sys.draw.Canvas c, int hour, int minute, int second, int millisecond ->
c.circle(360,232,154,3,GREEN);
for( int i=0; i<60; i++ ) {
f64 turn=i/60.0;
bool major=i-i/5*5==0;
int inner=major ? 133 : 143;
- int x0=360+_sin_noInline(turn)*inner, y0=232-_sin_noInline(turn+0.25)*inner;
- int x1=360+_sin_noInline(turn)*149, y1=232-_sin_noInline(turn+0.25)*149;
+ int x0=360+_sin(turn)*inner, y0=232-_sin(turn+0.25)*inner;
+ int x1=360+_sin(turn)*149, y1=232-_sin(turn+0.25)*149;
c.line(x0,y0,x1,y1,major ? 3 : 1,GREEN);
}
c.text(349,100,"12",2,GREEN); c.text(484,227,"3",2,GREEN);
c.text(357,354,"6",2,GREEN); c.text(230,227,"9",2,GREEN);
f64 seconds=second+millisecond/1000.0;
f64 minutes=minute+seconds/60.0;
- _hand_noInline(c,(hour-hour/12*12+minutes/60.0)/12.0,78,8,GREEN);
- _hand_noInline(c,minutes/60.0,112,5,GREEN);
- _hand_noInline(c,seconds/60.0,128,2,0xc3ffcb);
+ _hand(c,(hour-hour/12*12+minutes/60.0)/12.0,78,8,GREEN);
+ _hand(c,minutes/60.0,112,5,GREEN);
+ _hand(c,seconds/60.0,128,2,0xc3ffcb);
c.fillCircle(360,232,6,GREEN);
};