611 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			611 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!doctype html>
 | 
						|
<html>
 | 
						|
 | 
						|
<head>
 | 
						|
	<meta charset="utf-8">
 | 
						|
	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 | 
						|
 | 
						|
	<title>Renode: Easy CI for your Weird Hardware</title>
 | 
						|
 | 
						|
	<link rel="stylesheet" href="dist/reset.css">
 | 
						|
	<link rel="stylesheet" href="dist/reveal.css">
 | 
						|
	<link rel="stylesheet" href="dist/theme/black.css">
 | 
						|
 | 
						|
	<!-- Theme used for syntax highlighted code -->
 | 
						|
	<link rel="stylesheet" href="plugin/highlight/monokai.css">
 | 
						|
</head>
 | 
						|
 | 
						|
<!--
 | 
						|
* Emulators are useful tools
 | 
						|
	- PC emulator (e.g. Docker on Mac, WSL on Linux)
 | 
						|
	- NES emulator -- fun and games, realtime output
 | 
						|
		- Also have debugging emulators
 | 
						|
	- Renode
 | 
						|
 | 
						|
* Renode Stack
 | 
						|
	- CPU cores written in C
 | 
						|
		- arm, i386, ppc, riscv, sparc, xtensa
 | 
						|
	- Windows, Mac, Linux
 | 
						|
	- Peripherals and UI written in C#
 | 
						|
	- Extensible via Python and C#
 | 
						|
		- Write once. Run anywhere. Using C# to define new peripherals
 | 
						|
 | 
						|
* Three major users
 | 
						|
	- Designers of new boards
 | 
						|
	- Reverse engineering exsisting hardware
 | 
						|
	- Silicon designers
 | 
						|
 | 
						|
* Designers of new boards
 | 
						|
	- One or more chips
 | 
						|
	- How are they connected?
 | 
						|
	- What weird hardware exists?
 | 
						|
 | 
						|
	* Concurrent emulation of multiple devices
 | 
						|
		- Can connect multiple devices, e.g. via UART, GPIO, SPI, Ethernet, CAN...
 | 
						|
		- All devices are emulated using the same time source
 | 
						|
		- Helps to debug timing differences with different processors on a board
 | 
						|
	
 | 
						|
	* Board definition format
 | 
						|
		- Easily define memory layout
 | 
						|
		- Easily move blocks around
 | 
						|
		- Only define what's necessary
 | 
						|
		- You don't need to be perfect, just good enough!
 | 
						|
	
 | 
						|
	* Can read SVD files
 | 
						|
 | 
						|
	* Hardware has Similarities
 | 
						|
		- Picture of existing register sets
 | 
						|
		- There are only so many combinations
 | 
						|
		- Rip. Mix. Burn. Many chips are just copies of one another.
 | 
						|
 | 
						|
	* Tests in CI
 | 
						|
 | 
						|
* Reverse engineering existing hardware
 | 
						|
 | 
						|
	* If it's a supported architecture, it's easy to run code
 | 
						|
	* LoadBinary and set PC
 | 
						|
	* Can skip much of the boot ROM
 | 
						|
	* Attach GDB
 | 
						|
	* Reproducible makes it easy to test theories
 | 
						|
 | 
						|
* Developing new Silicon blocks
 | 
						|
 | 
						|
	* Betrusted hardware
 | 
						|
		- Create a new design in LiteX / Verilog
 | 
						|
		- Document the design
 | 
						|
		- Create a model
 | 
						|
		- Timing isn't as critical
 | 
						|
 | 
						|
-->
 | 
						|
 | 
						|
<body>
 | 
						|
	<div class="reveal">
 | 
						|
		<div class="slides">
 | 
						|
			<section>
 | 
						|
				<section>
 | 
						|
					<h2>Renode</h2>
 | 
						|
					<p>I find it a useful tool. Maybe you will, too!
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>About Me: I Do Weird Hardware</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Simmel: Contact Tracing with Audio</li>
 | 
						|
						<li>Chibitronics: Programming Stickers with Audio</li>
 | 
						|
						<li>Novena: Open Source Laptop</li>
 | 
						|
						<li>Senoko: Open Source Power Board for Novena</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Hardware with Embedded Software</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Software needs to be written</li>
 | 
						|
						<li class="fragment">Software needs to be <strong>tested</strong></li>
 | 
						|
						<li class="fragment">Software needs to be <i>debugged</i></li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>About Renode</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Whole-System Emulator</li>
 | 
						|
						<li>Supports concurrent emulation</li>
 | 
						|
						<li>Extensible with C# and Python</li>
 | 
						|
						<li>Windows, Mac, Linux</li>
 | 
						|
						<li>MIT Licensed</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>About This Talk</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Overview of Emulators</li>
 | 
						|
						<li>Oevrview of Weird Hardware</li>
 | 
						|
						<li>Cool things you can do</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Who will find this interesting?</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Creators: Those making new boards or hardware</li>
 | 
						|
						<li>Integrators: Running CI on firmware files</li>
 | 
						|
						<li>Reverse Engineers: Understanding new hardware and firmware</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Creators: Making New Things!</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Reusing an existing platform</li>
 | 
						|
						<li>Reusing an existing microcontroller</li>
 | 
						|
						<li>New microcontroller fron existing family</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Integrators: Making Sure Nothing Broke!</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Hardware testing incompatible with cloud</li>
 | 
						|
						<ul>
 | 
						|
							<li>...it sure is effective, though</li>
 | 
						|
						</ul>
 | 
						|
						<li>Hardware crunch makes it difficult to get hardware</li>
 | 
						|
						<li>Downloading software is much cheaper than shipping</li>
 | 
						|
						<li>Can run tests on every code push</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Reverse Engineers: What Is This Blob Doing?</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Staring at code flow is enlightening, but time-consuming</li>
 | 
						|
						<li>What is it doing and how does it get there?</li>
 | 
						|
						<li>How can we make it do $x?</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
			</section>
 | 
						|
			<section>
 | 
						|
				<section data-transition="fade-out">
 | 
						|
					<h2>What is an Emulator?</h2>
 | 
						|
					<img class="fragment" src="media/bbs-example.png">
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade">
 | 
						|
					<h2>What is an Emulator?</h2>
 | 
						|
					<img src="media/DEC_VT100_terminal_cropped.jpg">
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade-in">
 | 
						|
					<h2>What is an Emulator?</h2>
 | 
						|
					<img src="media/bbs-example.png">
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Whole-System Emulator</h2>
 | 
						|
					<img src="media/fceux-smb.png">
 | 
						|
					<!--
 | 
						|
					<ul>
 | 
						|
						<li>Wii Virtual Console</li>
 | 
						|
						<li>VirtualBox</li>
 | 
						|
						<li>Parallels</li>
 | 
						|
					</ul>
 | 
						|
					-->
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Whole-System Emulator</h2>
 | 
						|
					<img src="media/fceux-smb-debug.png">
 | 
						|
					<!--
 | 
						|
					<ul>
 | 
						|
						<li>Wii Virtual Console</li>
 | 
						|
						<li>VirtualBox</li>
 | 
						|
						<li>Parallels</li>
 | 
						|
					</ul>
 | 
						|
					-->
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Transparent Emulator</h2>
 | 
						|
					<ul>
 | 
						|
						<li>WSL2/Docker</li>
 | 
						|
						<li>qemu on Linux</li>
 | 
						|
						<li>Rosetta on Mac</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Renode Is Many of These</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Console: Able to present an interactive environment</li>
 | 
						|
						<li>Transparent: Can run in CI via Robot commands</li>
 | 
						|
						<li>Debugger: Has a GDB server built in</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
			</section>
 | 
						|
 | 
						|
			<section>
 | 
						|
				<section data-transition="fade-out">
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img class="fragment" src="media/bluenrg-block-diagram.png">
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade">
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<ul>
 | 
						|
						<li>A system of devices</li>
 | 
						|
						<li>One or more CPU</li>
 | 
						|
						<li>One or more buses</li>
 | 
						|
						<li>One or more blocks of memory</li>
 | 
						|
						<li>Some I/O</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade-out">
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img class="fragment" src="media/bluenrg-block-diagram.png">
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade">
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img src="media/bluenrg-block-diagram-no-extra-bits.png">
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade">
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img src="media/bluenrg-block-diagram-cpu.png">
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade">
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img src="media/bluenrg-block-diagram-memories.png">
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade-in">
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img src="media/bluenrg-block-diagram-peripherals.png">
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img src="media/bluenrg-peripherals.png">
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img src="media/bluenrg-memory-map.png">
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>What is a Computer?</h2>
 | 
						|
					<img src="media/conceptual-diagram.png">
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Defining a Computer in Renode</h2>
 | 
						|
					<pre><code data-trim>
 | 
						|
						flash: Memory.MappedMemory @ sysbus 0x00000000
 | 
						|
							size: 0x00008000
 | 
						|
 | 
						|
						sram: Memory.MappedMemory @ sysbus 0x20000000
 | 
						|
							size: 0x00001000
 | 
						|
	
 | 
						|
						nvic: IRQControllers.NVIC @ sysbus 0xE000E000
 | 
						|
							IRQ -> cpu@0
 | 
						|
 | 
						|
						cpu: CPU.CortexM @ sysbus
 | 
						|
							nvic: nvic
 | 
						|
							cpuType: "cortex-m0+"
 | 
						|
							PerformanceInMips: 24
 | 
						|
					</code></pre>
 | 
						|
				</section>
 | 
						|
			</section>
 | 
						|
 | 
						|
			<section>
 | 
						|
				<h2>That's Nice, but What About...</h2>
 | 
						|
				<ol>
 | 
						|
					<li>Loading firmware?</li>
 | 
						|
					<li>Adding peripherals?</li>
 | 
						|
				</ol>
 | 
						|
			</section>
 | 
						|
 | 
						|
			<section>
 | 
						|
				<section>
 | 
						|
					<h2>What is "Firmware"?</h2>
 | 
						|
					<blockquote class="fragment strike">Firmware is a series of instructions executed by the CPU in
 | 
						|
						order to accomplish a task</blockquote>
 | 
						|
					<blockquote class="fragment">Firmware is Memory</blockquote>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Loading Firmware in Renode</h2>
 | 
						|
					<pre><code data-trim>
 | 
						|
						sysbus LoadELF @firmware.elf
 | 
						|
					</code></pre>
 | 
						|
					<pre class="fragment"><code data-trim>
 | 
						|
						sysbus LoadBinary @rom.bin 0x20000000
 | 
						|
					</code></pre>
 | 
						|
					<pre class="fragment"><code data-trim>
 | 
						|
						sysbus LoadSymbolsFrom @rom.elf
 | 
						|
					</code></pre>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>How does Renode Interact With $VENDOR_TOOL?</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Hopefully your vendor tool produces ELF files</li>
 | 
						|
						<li class="fragment">At the end of the day, it's all bytes. Just use <code>LoadBinary</code>!
 | 
						|
						</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>What About Boot ROMs?</h2>
 | 
						|
					<ol>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Initialize peripherals</li>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Check for boot override</li>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Check for low-power state</li>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Load firmware into RAM</li>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Validate firmware</li>
 | 
						|
						<li>Jump to loaded program</li>
 | 
						|
					</ol>
 | 
						|
					<pre class="fragment"><code data-trim>
 | 
						|
						sysbus.cpu VectorTableOffset 0x20000000
 | 
						|
						sysbus.cpu PC 0x20000c00
 | 
						|
					</code></pre>
 | 
						|
				</section>
 | 
						|
			</section>
 | 
						|
			<section>
 | 
						|
				<section>
 | 
						|
					<h2>What about New Peripherals?</h2>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>It's All About Small Victories</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Serial ports are super rewarding</li>
 | 
						|
						<li>They're also usually simple!</li>
 | 
						|
						<li>They are easy to script</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Reusing an Existing Port</h2>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Steps to Set Up a Serial Port</h2>
 | 
						|
					<ol>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Enable peripheral</li>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Set up clock</li>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Mux GPIOs</li>
 | 
						|
						<li class="fragment strike semi-fade-out" data-fragment-index="1">Calculate baud rate</li>
 | 
						|
						<li>Write to UART TX register</li>
 | 
						|
					</ol>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Steps to Set Up a Serial Port</h2>
 | 
						|
					<img src="media/renode-xous-kernel-uart.png">
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Steps to Set Up a Serial Port</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Interrupt Support</li>
 | 
						|
						<li>DMA</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Example Serial Port</h2>
 | 
						|
					<pre><code class="cs" data-trim>
 | 
						|
						{(long)Registers.RxTx, new DoubleWordRegister(this)
 | 
						|
							.WithValueField(0, 8,
 | 
						|
								writeCallback: (_, value) => {
 | 
						|
									this.TransmitCharacter((byte)value);
 | 
						|
								},
 | 
						|
								valueProviderCallback: _ => {
 | 
						|
									if(!TryGetCharacter(out var character))
 | 
						|
									{
 | 
						|
										this.Log(LogLevel.Warning, "Empty Rx FIFO.");
 | 
						|
									}
 | 
						|
									return character;
 | 
						|
								})
 | 
						|
						},
 | 
						|
					</code></pre>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>What about Missing Definitions?</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Most registers are unused</li>
 | 
						|
						<li>Most writes can be ignored</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade-out">
 | 
						|
					<h2>Advantages of Emulation</h2>
 | 
						|
					<img src="media/betrusted-soc-uart-mux.png">
 | 
						|
				</section>
 | 
						|
				<section data-transition="fade-in">
 | 
						|
					<h2>Advantages of Emulation</h2>
 | 
						|
					<img src="media/renode-xous-double-uart-tiled.png">
 | 
						|
				</section>
 | 
						|
			</section>
 | 
						|
			<!-- 
 | 
						|
			<section>
 | 
						|
				<section>
 | 
						|
					<h2>Example of Weird Hardware</h2>
 | 
						|
					<ul>
 | 
						|
						<li>NRF52840</li>
 | 
						|
						<li>LM74 Temperature Sensor</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Example of Weird Hardware</h2>
 | 
						|
					<ul>
 | 
						|
						<li>NRF52833</li>
 | 
						|
						<li>LM74 Temperature Sensor</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Example of Weird Hardware</h2>
 | 
						|
					<ul>
 | 
						|
						<li>BlueNRG1</li>
 | 
						|
						<li>LM74 Temperature Sensor</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Example of Weird Hardware</h2>
 | 
						|
					<ul>
 | 
						|
						<li>RISC-V</li>
 | 
						|
						<li>FPGA-based framebuffer</li>
 | 
						|
						<li>Initial graphical demo in 1 hour</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
			</section>
 | 
						|
			<section>
 | 
						|
				<section>
 | 
						|
					<h2>What makes hardware "Weird"?</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Unusual CPU architecture</li>
 | 
						|
						<li>Different model of chip than commonly found</li>
 | 
						|
						<li>Additional hardware</li>
 | 
						|
						<li>More CPUs per board</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Unusual CPU architecture</h2>
 | 
						|
					Sorry, can't help
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Different model CPU</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Maybe it's just a variant</li>
 | 
						|
						<li>Perhaps memory regions were shuffled</li>
 | 
						|
						<li>Does it use the same hardware block as someone else?</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>New hardware version</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Do you use the new, specialized features?</li>
 | 
						|
						<li>Lots of UARTs support Infrared. Do you need that?</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Completely new hardware</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Time to break out C#</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
			</section> -->
 | 
						|
			<section>
 | 
						|
 | 
						|
				<section>
 | 
						|
					<h2>Robot Framework: Running Tests in CI</h2>
 | 
						|
					<pre><code class="hljs" data-trim>
 | 
						|
							*** Test Cases ***
 | 
						|
							Should Read Acceleration
 | 
						|
								Create Machine
 | 
						|
								Create Terminal Tester    ${UART}
 | 
						|
							
 | 
						|
								Execute Command   sysbus.twi1.lis2ds12 AccelerationX 10
 | 
						|
								Execute Command   sysbus.twi1.lis2ds12 AccelerationY 5
 | 
						|
								Execute Command   sysbus.twi1.lis2ds12 AccelerationZ -5
 | 
						|
							
 | 
						|
								Start Emulation
 | 
						|
							
 | 
						|
								Wait For Line On Uart  x 9.997213 , y 4.997410 , z -4.999803
 | 
						|
						</code></pre>
 | 
						|
				</section>
 | 
						|
			</section>
 | 
						|
			<section>
 | 
						|
				<section>
 | 
						|
					<h2>SVD Files</h2>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Logging Memory Accesses</h2>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Debugging with GDB</h2>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Software Assumes Hardware Works</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Rarely checks for sane ranges (why would you?)</li>
 | 
						|
						<li>TOC-TOU</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
				<section>
 | 
						|
					<h2>Incremental Changes</h2>
 | 
						|
					<ul>
 | 
						|
						<li>Small changes are very rewrding</li>
 | 
						|
						<li>Device will work with only partial implementation</li>
 | 
						|
					</ul>
 | 
						|
				</section>
 | 
						|
			</section>
 | 
						|
		</div>
 | 
						|
	</div>
 | 
						|
 | 
						|
	<script src="dist/reveal.js"></script>
 | 
						|
	<script src="plugin/notes/notes.js"></script>
 | 
						|
	<script src="plugin/zoom/zoom.js"></script>
 | 
						|
	<script src="plugin/markdown/markdown.js"></script>
 | 
						|
	<script src="plugin/highlight/highlight.js"></script>
 | 
						|
	<script type="text/javascript" src="js/robot.js"></script>
 | 
						|
	<script>
 | 
						|
		/** This used to be a part of Reveal.js, but was removed at some point */
 | 
						|
		function getQueryHash() {
 | 
						|
			function deserialize(value) {
 | 
						|
				if (typeof value === 'string') {
 | 
						|
					if (value === 'null') return null;
 | 
						|
					else if (value === 'true') return true;
 | 
						|
					else if (value === 'false') return false;
 | 
						|
					else if (value.match(/^-?[\d\.]+$/)) return parseFloat(value);
 | 
						|
				}
 | 
						|
				return value;
 | 
						|
			}
 | 
						|
 | 
						|
			let query = {};
 | 
						|
			location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi, a => {
 | 
						|
				query[a.split('=').shift()] = a.split('=').pop();
 | 
						|
			});
 | 
						|
			// Basic deserialization
 | 
						|
			for (let i in query) {
 | 
						|
				let value = query[i];
 | 
						|
 | 
						|
				query[i] = deserialize(unescape(value));
 | 
						|
			}
 | 
						|
 | 
						|
			// Do not accept new dependencies via query config to avoid
 | 
						|
			// the potential of malicious script injection
 | 
						|
			if (typeof query['dependencies'] !== 'undefined') delete query['dependencies'];
 | 
						|
 | 
						|
			return query;
 | 
						|
 | 
						|
		}
 | 
						|
		var presenter = !!getQueryHash().s;
 | 
						|
		// More info about initialization & config:
 | 
						|
		// - https://revealjs.com/initialization/
 | 
						|
		// - https://revealjs.com/config/
 | 
						|
		Reveal.initialize({
 | 
						|
			hash: true,
 | 
						|
 | 
						|
			controls: presenter ? false : true,
 | 
						|
			progress: true,
 | 
						|
			history: true,
 | 
						|
			center: true,
 | 
						|
			controlsTutorial: presenter ? false : true,
 | 
						|
 | 
						|
			slideNumber: presenter ? null : 'c/t',
 | 
						|
 | 
						|
			// The "normal" size of the presentation, aspect ratio will be preserved
 | 
						|
			// when the presentation is scaled to fit different resolutions. Can be
 | 
						|
			// specified using percentage units.
 | 
						|
			width: 960,
 | 
						|
			height: 700,
 | 
						|
 | 
						|
			// Factor of the display size that should remain empty around the content
 | 
						|
			margin: 0.1,
 | 
						|
 | 
						|
			multiplex: {
 | 
						|
				// Example values. To generate your own, see the socket.io server instructions.
 | 
						|
				secret: getQueryHash().s || null,
 | 
						|
				id: '160c0567ef5ca18f',
 | 
						|
				url: 'https://p.xobs.io/'
 | 
						|
			},
 | 
						|
 | 
						|
 | 
						|
			// Bounds for smallest/largest possible scale to apply to content
 | 
						|
			minScale: 0.02,
 | 
						|
			maxScale: 5.5,
 | 
						|
 | 
						|
			transition: 'slide', // none/fade/slide/convex/concave/zoom
 | 
						|
 | 
						|
			highlight: {
 | 
						|
				beforeHighlight: hljs => hljs.registerLanguage('robot', window.hljsDefineRobot)
 | 
						|
			},
 | 
						|
 | 
						|
			// Don't forget to add the dependencies
 | 
						|
			dependencies: [
 | 
						|
				{ src: 'https://reveal-multiplex.glitch.me/socket.io/socket.io.js', async: true },
 | 
						|
				{ src: 'https://reveal-multiplex.glitch.me/client.js', async: true }
 | 
						|
			],
 | 
						|
 | 
						|
			// Learn about plugins: https://revealjs.com/plugins/
 | 
						|
			plugins: [RevealMarkdown, RevealHighlight, RevealZoom]
 | 
						|
		});
 | 
						|
 | 
						|
 | 
						|
	</script>
 | 
						|
</body>
 | 
						|
 | 
						|
</html> |