Skip to content

Commit a431f62

Browse files
aykevldeadprogram
authored andcommitted
Add a playground view on the homepage
1 parent 8a74a2b commit a431f62

File tree

6 files changed

+294
-1
lines changed

6 files changed

+294
-1
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "static/playground"]
2+
path = static/playground
3+
url = https://github.com/tinygo-org/playground.git

config.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,12 @@ enable = true
9191
# change content/<lang>/... to content/...
9292
from = "content/(.*?)/(.*?)"
9393
to = "content/$2"
94+
95+
# Add some extra headers to the development server.
96+
# This is only relevant with `hugo serve`.
97+
[server]
98+
[[server.headers]]
99+
for = '/**'
100+
[server.headers.values]
101+
Cross-Origin-Opener-Policy = "same-origin"
102+
Cross-Origin-Embedder-Policy = "require-corp"

content/_index.md

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,66 @@ Ready to get started? [Click here](getting-started).
2828

2929
{{% /blocks/lead %}}
3030

31-
{{< blocks/section color="primary-light" type="row" >}}
31+
{{% blocks/section color="primary-light" %}}
32+
<link rel="stylesheet" href="playground/simulator.css">
33+
<script type="module" src="playground.js"></script>
34+
<div class="col">
35+
<div class="container" id="playground">
36+
<h1 class="text-center">Try TinyGo</h1>
37+
<div class="row px-0">
38+
<div class="col col-auto">
39+
<div class="input-group mb-3">
40+
<span class="input-group-text">Example</span>
41+
<select class="form-select example_select" disabled>
42+
<option value="hello">Hello world</option>
43+
<option value="arduino" selected>Blinking LED (Arduino Uno)</option>
44+
<option value="circuitplay_express">RGB LEDs (Adafruit Circuit Playground Express)</option>
45+
<option value="gopher_badge">Display (Gopher Badge)</option>
46+
</select>
47+
</div>
48+
</div>
49+
<div class="col col-auto">
50+
<button class="btn btn-secondary playground-btn-flash" disabled>Download binary</button>
51+
</div>
52+
</div>
53+
<textarea placeholder="Loading..." class="form-control input" rows="20" style="font-family: monospace; tab-size: 4" spellcheck="false"></textarea>
54+
<div class="simulator inline">
55+
<div class="schematic-buttons">
56+
<button class="schematic-button-pause schematic-button" title="Pause/resume the simulation">
57+
<!-- only one of these two images is visible at a time -->
58+
<img src="playground/resources/codicon/debug-pause.svg" class="button-img-pause"/>
59+
<img src="playground/resources/codicon/play.svg" class="button-img-play"/>
60+
</button>
61+
</div>
62+
<svg class="schematic">
63+
<g class="schematic-wrapper" style="transform: translate(50%, 50%)">
64+
<g class="schematic-parts"></g>
65+
<g class="schematic-wires"></g>
66+
</g>
67+
</svg>
68+
<div class="panels">
69+
<div class="tabbar">
70+
<span class="tab active panel-tab-terminal"><a>Terminal</a></span>
71+
<span class="tab"><a>Properties</a></span>
72+
<span class="tab"><a>Add</a></span>
73+
</div>
74+
<div class="tabcontent active terminal-box">
75+
<textarea class="terminal" readonly></textarea>
76+
</div>
77+
<div class="tabcontent panel-properties">
78+
<div class="content"></div>
79+
</div>
80+
<div class="tabcontent panel-add">
81+
Loading...
82+
</div>
83+
</div>
84+
<div class="schematic-tooltip"></div>
85+
</div>
86+
</div>
87+
</div>
88+
{{% /blocks/section %}}
89+
90+
{{< blocks/section color="primary" type="row" >}}
3291
{{% blocks/feature icon="fa-lightbulb" title="TinyGo Playground" url="https://play.tinygo.org/" %}}
3392
Try TinyGo online
3493
{{% /blocks/feature %}}

netlify.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212
[context.release.environment]
1313
HUGO_ENV = "production"
1414

15+
# Required for the playground (it needs SharedArrayBuffer).
16+
[[headers]]
17+
for = "/*"
18+
[headers.values]
19+
Cross-Origin-Opener-Policy = "same-origin"
20+
Cross-Origin-Embedder-Policy = "require-corp"
21+
1522
[[redirects]]
1623
from = "/bluetooth"
1724
to = "https://github.com/tinygo-org/bluetooth#go-bluetooth"

static/playground

Submodule playground added at d816b8d

static/playground.js

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
import { Simulator } from './playground/simulator.js';
2+
3+
// Note: to test this locally, run the playground server!
4+
// Run the following in a terminal:
5+
//
6+
// cd static/playground
7+
// go run .
8+
//
9+
const PLAYGROUND_API = location.hostname == 'localhost' ? 'http://localhost:8080/api' : 'https://playground-bttoqog3vq-uc.a.run.app/api';
10+
11+
// Initialize the playground embedded in the homepage.
12+
addEventListener('DOMContentLoaded', async () => {
13+
let playground = document.querySelector('#playground');
14+
let exampleSelect = playground.querySelector('.example_select');
15+
let root = playground.querySelector('.simulator');
16+
let textarea = playground.querySelector('textarea.input');
17+
let firmwareButton = playground.querySelector('.playground-btn-flash');
18+
19+
// Load simulator.
20+
let state = structuredClone(examples[exampleSelect.value]);
21+
textarea.value = state.code;
22+
let simulator = new Simulator({
23+
root: root,
24+
input: textarea,
25+
firmwareButton: firmwareButton,
26+
baseURL: new URL('/playground/', document.baseURI),
27+
apiURL: PLAYGROUND_API,
28+
});
29+
await simulator.setState(state, state.target);
30+
31+
// Respond to changes in the example select box.
32+
exampleSelect.disabled = false;
33+
exampleSelect.addEventListener('change', async () => {
34+
exampleSelect.disabled = true;
35+
state = structuredClone(examples[exampleSelect.value]);
36+
textarea.value = state.code;
37+
await simulator.setState(state, state.target);
38+
exampleSelect.disabled = false;
39+
})
40+
});
41+
42+
43+
const exampleHello = `// You can edit this code!
44+
package main
45+
46+
func main() {
47+
println("hello world!")
48+
}`;
49+
50+
const exampleBlink = `// You can edit this code!
51+
package main
52+
53+
import (
54+
"machine"
55+
"time"
56+
)
57+
58+
func main() {
59+
led := machine.LED
60+
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
61+
for {
62+
led.High()
63+
time.Sleep(time.Second/2)
64+
65+
led.Low()
66+
time.Sleep(time.Second/2)
67+
}
68+
}`;
69+
70+
const exampleST7789 = `package main
71+
72+
import (
73+
"machine"
74+
"image/color"
75+
"tinygo.org/x/drivers/st7789"
76+
)
77+
78+
func main() {
79+
// configure the display
80+
machine.SPI0.Configure(machine.SPIConfig{
81+
Frequency: 62_500_000, // 62.5MHz
82+
Mode: 3,
83+
SCK: machine.SPI0_SCK_PIN,
84+
SDI: machine.SPI0_SDI_PIN,
85+
SDO: machine.SPI0_SDO_PIN,
86+
})
87+
display := st7789.New(machine.SPI0,
88+
machine.TFT_RST, // reset
89+
machine.TFT_WRX, // data/command
90+
machine.TFT_CS, // chip select
91+
machine.TFT_BACKLIGHT) // backlight
92+
display.Configure(st7789.Config{
93+
Rotation: st7789.ROTATION_270,
94+
Height: 320,
95+
})
96+
97+
width, height := display.Size()
98+
99+
white := color.RGBA{255, 255, 255, 255}
100+
red := color.RGBA{255, 0, 0, 255}
101+
blue := color.RGBA{0, 0, 255, 255}
102+
green := color.RGBA{0, 255, 0, 255}
103+
black := color.RGBA{0, 0, 0, 255}
104+
105+
display.FillRectangle(0, 0, width/2, height/2, white)
106+
display.FillRectangle(width/2, 0, width/2, height/2, red)
107+
display.FillRectangle(0, height/2, width/2, height/2, green)
108+
display.FillRectangle(width/2, height/2, width/2, height/2, blue)
109+
display.FillRectangle(width/4, height/4, width/2, height/2, black)
110+
}`;
111+
112+
const exampleLEDs = `package main
113+
114+
import (
115+
"image/color"
116+
"machine"
117+
"time"
118+
119+
"tinygo.org/x/drivers/ws2812"
120+
)
121+
122+
func main() {
123+
// Set up the ring of RGB LEDs.
124+
pin := machine.WS2812
125+
pin.Configure(machine.PinConfig{Mode: machine.PinOutput})
126+
ws := ws2812.New(pin)
127+
leds := make([]color.RGBA, 10)
128+
129+
for cycle := uint8(0); ; cycle++ {
130+
// Calculate a new color for each LED.
131+
for i := range leds {
132+
leds[i] = colorWheel(cycle*2 + uint8(i*8))
133+
}
134+
135+
// Write colors to the LED ring.
136+
ws.WriteColors(leds)
137+
138+
// Wait a bit each loop (running at around 30fps).
139+
time.Sleep(time.Second / 30)
140+
}
141+
}
142+
143+
// Pick a color from the color wheel (red, then, green, then blue, and back to
144+
// red).
145+
func colorWheel(index uint8) color.RGBA {
146+
index = 255-index
147+
if index < 85 {
148+
return color.RGBA{R: 255 - index*3, B: index * 3}
149+
} else if index < 170 {
150+
return color.RGBA{G: (index - 85) * 3, B: 255 - (index-85)*3}
151+
} else {
152+
return color.RGBA{R: (index - 170) * 3, G: 255 - (index-170)*3}
153+
}
154+
}`;
155+
156+
var examples = {
157+
// Simple "hello world" example.
158+
hello: {
159+
target: 'console',
160+
code: exampleHello,
161+
parts: {
162+
main: {
163+
location: 'parts/console.json',
164+
x: 0,
165+
y: 0,
166+
}
167+
},
168+
wires: [],
169+
},
170+
171+
// Simple "blinky light" example.
172+
// The Arduino Uno, despite its limitations, is very well known and many
173+
// people have one. So it seems like a good testcase.
174+
arduino: {
175+
target: 'arduino',
176+
code: exampleBlink,
177+
parts: {
178+
main: {
179+
location: 'parts/arduino.json',
180+
x: 0,
181+
y: 0,
182+
}
183+
},
184+
wires: [],
185+
},
186+
187+
// Commonly used board, and a nice demo with LEDs.
188+
circuitplay_express: {
189+
target: 'circuitplay_express',
190+
code: exampleLEDs,
191+
parts: {
192+
main: {
193+
location: 'parts/circuitplay-express.json',
194+
x: 0,
195+
y: 0,
196+
},
197+
},
198+
wires: [],
199+
},
200+
201+
// Our own Gopher Badge, which importantly has a display!
202+
gopher_badge: {
203+
target: 'gopher_badge',
204+
code: exampleST7789,
205+
parts: {
206+
main: {
207+
location: 'parts/gopher-badge.json',
208+
x: 0,
209+
y: 0,
210+
},
211+
},
212+
wires: [],
213+
},
214+
};

0 commit comments

Comments
 (0)