diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,4 +1,4 @@
-arduino-copilot (0.0.1) unstable; urgency=medium
+arduino-copilot (1.0.0) unstable; urgency=medium
 
   * First release.
 
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
+Arduino programming in haskell using the Copilot stream DSL
+
+See Copilot.Arduino for details on how to use write a program using this
+library.
+
+Several examples are included in the examples/ directory, and each have
+their own README explaining how to use them.
diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -0,0 +1,2 @@
+* analog pins
+* serial console support (involves arrays of bytes)
diff --git a/arduino-copilot.cabal b/arduino-copilot.cabal
--- a/arduino-copilot.cabal
+++ b/arduino-copilot.cabal
@@ -1,5 +1,5 @@
 Name: arduino-copilot
-Version: 0.0.1
+Version: 1.0.0
 Cabal-Version: >= 1.8
 License: BSD3
 Maintainer: Joey Hess <id@joeyh.name>
@@ -9,13 +9,13 @@
 License-File: LICENSE
 Build-Type: Simple
 Category: Embedded, Language
-Synopsis: Arduino programming in haskell using the stream DSL
+Synopsis: Arduino programming in haskell using the Copilot stream DSL
 Description:
  arduino-copilot contains the basic building blocks to program your
  Arduino Nano, Arduino Uno or compatible hardware using Haskell
  and Functional Reactive Programming (FRP).
  .
- arduino-copilot uses the Copilot stream domain-specific language (DSL)
+ arduino-copilot uses the Copilot stream DSL (domain-specific language)
  to generate an Arduino sketch, which can be loaded in the Arduino IDE
  and uploaded to the board. Other methods of deploying sketches to the
  Arduino, such as the Arduino-Makefile, can also be used with a sketch
@@ -25,30 +25,39 @@
  desired behavior of the Arduino. This is all the code needed to make
  it blink its LED:
  .
- -- > import Arduino
+ -- > import Copilot.Arduino
  -- > main = arduino $ do
- -- >    led =: clk (period 2) (phase 1)
- -- >    delay =: const16 100
+ -- >    led =: blinking
+ -- >    delay =: constant 100
  .
  Copilot is a stream (i.e., infinite lists) domain-specific language
- (DSL) in Haskell that compiles into embedded C.  Copilot contains an
+ (DSL) in Haskell that compiles into embedded C. Copilot contains an
  interpreter, multiple back-end compilers, and other verification tools.
- A tutorial, bug reports, and todos are available at
- <https://github.com/Copilot-Language/copilot-discussion>.
+ <https://copilot-language.github.io/>
 Extra-Source-Files:
+  README
   CHANGELOG
   TODO
   stack.yaml
-  demo/Makefile
-  demo/README
-  demo/demo.hs
-  demo/pre-build-hook.sh
+  examples/blink/Makefile
+  examples/blink/README
+  examples/blink/demo.hs
+  examples/blink/pre-build-hook.sh
+  examples/button/Makefile
+  examples/button/README
+  examples/button/demo.hs
+  examples/button/pre-build-hook.sh
 
 Library
   GHC-Options: -Wall -fno-warn-tabs
   Hs-Source-Dirs: src
   Exposed-Modules:
-    Arduino
+    Copilot.Arduino
+    Copilot.Arduino.Nano
+    Copilot.Arduino.Uno
+    Copilot.Arduino.Internals
+  Other-Modules:
+    Copilot.Arduino.Main
   Build-Depends:
     base (>= 4.5 && < 5),
     copilot (== 3.1.*),
@@ -56,7 +65,8 @@
     filepath,
     directory,
     mtl,
-    unix
+    unix,
+    optparse-applicative (>= 0.14.1)
 
 source-repository head
   type: git
diff --git a/demo/Makefile b/demo/Makefile
deleted file mode 100644
--- a/demo/Makefile
+++ /dev/null
@@ -1,127 +0,0 @@
-# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
-BOARD_TAG    = uno
-include /usr/share/arduino/Arduino.mk
-
-# --- leonardo (or pro micro w/leo bootloader)
-#BOARD_TAG    = leonardo
-#MONITOR_PORT = /dev/ttyACM0
-#include /usr/share/arduino/Arduino.mk
-
-# --- mega2560 ide 1.0
-#BOARD_TAG    = mega2560
-#ARDUINO_PORT = /dev/ttyACM0
-#include /usr/share/arduino/Arduino.mk
-
-# --- mega2560 ide 1.6
-#BOARD_TAG    = mega
-#BOARD_SUB    = atmega2560
-#MONITOR_PORT = /dev/ttyACM0
-#ARDUINO_DIR  = /where/you/installed/arduino-1.6.5
-#include /usr/share/arduino/Arduino.mk
-
-# --- nano ide 1.0
-#BOARD_TAG    = nano328
-#MONITOR_PORT = /dev/ttyUSB0
-#include /usr/share/arduino/Arduino.mk
-
-# --- nano ide 1.6
-#BOARD_TAG   = nano
-#BOARD_SUB   = atmega328
-#ARDUINO_DIR = /where/you/installed/arduino-1.6.5
-#include /usr/share/arduino/Arduino.mk
-
-# --- pro mini
-#BOARD_TAG    = pro5v328
-#MONITOR_PORT = /dev/ttyUSB0
-#include /usr/share/arduino/Arduino.mk
-
-# --- sparkfun pro micro
-#BOARD_TAG         = promicro16
-#ALTERNATE_CORE    = promicro
-#BOARDS_TXT        = $(HOME)/arduino/hardware/promicro/boards.txt
-#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/promicro/bootloaders
-#BOOTLOADER_PATH   = caterina
-#BOOTLOADER_FILE   = Caterina-promicro16.hex
-#ISP_PROG     	   = usbasp
-#AVRDUDE_OPTS 	   = -v
-#include /usr/share/arduino/Arduino.mk
-
-# --- chipkit
-#BOARD_TAG = mega_pic32
-#MPIDE_DIR = /where/you/installed/mpide-0023-linux64-20130817-test
-#include /usr/share/arduino/chipKIT.mk
-
-# --- pinoccio
-#BOARD_TAG         = pinoccio256
-#ALTERNATE_CORE    = pinoccio
-#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/pinoccio/bootloaders
-#BOOTLOADER_PATH   = STK500RFR2/release_0.51
-#BOOTLOADER_FILE   = boot_pinoccio.hex
-#CFLAGS_STD        = -std=gnu99
-#CXXFLAGS_STD      = -std=gnu++11
-#include /usr/share/arduino/Arduino.mk
-
-# --- fio
-#BOARD_TAG = fio
-#include /usr/share/arduino/Arduino.mk
-
-# --- atmega-ng ide 1.6
-#BOARD_TAG    = atmegang
-#BOARD_SUB    = atmega168
-#MONITOR_PORT = /dev/ttyACM0
-#ARDUINO_DIR  = /where/you/installed/arduino-1.6.5
-#include /usr/share/arduino/Arduino.mk
-
-# --- arduino-tiny ide 1.0
-#ISP_PROG     	    = usbasp
-#BOARD_TAG          = attiny85at8
-#ALTERNATE_CORE     = tiny
-#ARDUINO_VAR_PATH   = $(HOME)/arduino/hardware/tiny/cores/tiny
-#ARDUINO_CORE_PATH  = $(HOME)/arduino/hardware/tiny/cores/tiny
-#AVRDUDE_OPTS 	    = -v
-#include /usr/share/arduino/Arduino.mk
-
-# --- arduino-tiny ide 1.6
-#ISP_PROG       = usbasp
-#BOARD_TAG      = attiny85at8
-#ALTERNATE_CORE = tiny
-#ARDUINO_DIR    = /where/you/installed/arduino-1.6.5
-#include /usr/share/arduino/Arduino.mk
-
-# --- damellis attiny ide 1.0
-#ISP_PROG       = usbasp
-#BOARD_TAG      = attiny85
-#ALTERNATE_CORE = attiny-master
-#AVRDUDE_OPTS   = -v
-#include /usr/share/arduino/Arduino.mk
-
-# --- damellis attiny ide 1.6
-#ISP_PROG       = usbasp
-#BOARD_TAG      = attiny
-#BOARD_SUB      = attiny85
-#ALTERNATE_CORE = attiny
-#F_CPU          = 16000000L
-#ARDUINO_DIR    = /where/you/installed/arduino-1.6.5
-#include /usr/share/arduino/Arduino.mk
-
-# --- teensy3
-#BOARD_TAG 	 = teensy31
-#ARDUINO_DIR = /where/you/installed/the/patched/teensy/arduino-1.0.6
-#include /usr/share/arduino/Teensy.mk
-
-# --- mighty 1284p
-#BOARD_TAG         = mighty_opt
-#BOARDS_TXT        = $(HOME)/arduino/hardware/mighty-1284p/boards.txt
-#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/mighty-1284p/bootloaders
-#BOOTLOADER_PATH   = optiboot
-#BOOTLOADER_FILE   = optiboot_atmega1284p.hex
-#ISP_PROG     	   = usbasp
-#AVRDUDE_OPTS 	   = -v
-#include /usr/share/arduino/Arduino.mk
-
-# --- atmega328p on breadboard
-#BOARD_TAG    = atmega328bb
-#ISP_PROG     = usbasp
-#AVRDUDE_OPTS = -v
-#BOARDS_TXT   = $(HOME)/arduino/hardware/breadboard/boards.txt
-#include /usr/share/arduino/Arduino.mk
diff --git a/demo/README b/demo/README
deleted file mode 100644
--- a/demo/README
+++ /dev/null
@@ -1,28 +0,0 @@
-This is a demo program using arduino-copilot. 
-
-To build the C code:
-
-	stack run demo
-
-The resulting `.ino` sketch can be loaded into the Arduino IDE and flashed
-to an Arduino board using the IDE.
-
-It simply flashes the Arduino's on board LED, so should work on most or all
-Arduino boards.
-
-## Arduino-Makefile integration
-
-The `Makefile` and `pre-build-hook.sh` show how to integrate arduino-copilot
-with <https://github.com/sudar/Arduino-Makefile>. This automates generating
-the C code, compiling that, and flashing it onto an Arduino Uno board,
-with a single command
-
-	make flash
-
-Note that you will need to manually build the C code once, as shown above
-, since the Arduino-Makefile expects to find a `.ino` file.
-
-The path in the `Makefile` to `Arduino.mk` may need to be adjusted (the
-default is the location where on a Debian system, `apt-get install
-arduino-mk` will install it). You may also adjust the `Makefile` to target
-a different board than the Arduino Uno.
diff --git a/demo/demo.hs b/demo/demo.hs
deleted file mode 100644
--- a/demo/demo.hs
+++ /dev/null
@@ -1,25 +0,0 @@
-{-# LANGUAGE RebindableSyntax #-}
-
-import Arduino
-
-flashing :: Stream Bool
-flashing = clk (period (2 :: Int16)) (phase 1)
-
-longer_and_longer :: Stream Int16
-longer_and_longer = counter true $ counter true false `mod` 64 == 0
-
-counter :: Stream Bool -> Stream Bool -> Stream Int16
-counter inc reset = cnt
-   where
-	cnt = if reset
-		then 0
-		else if inc
-			then z + 1
-			else z
-	z = [0] ++ cnt
-
-main :: IO ()
-main = arduino $ do
-	buttonpressed <- boolInput (Pin 14)
-	led =: buttonpressed || flashing
-	delay =: longer_and_longer
diff --git a/demo/pre-build-hook.sh b/demo/pre-build-hook.sh
deleted file mode 100644
--- a/demo/pre-build-hook.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-exec stack run demo -Wall -fno-warn-tabs
diff --git a/examples/blink/Makefile b/examples/blink/Makefile
new file mode 100644
--- /dev/null
+++ b/examples/blink/Makefile
@@ -0,0 +1,127 @@
+# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
+BOARD_TAG    = uno
+include /usr/share/arduino/Arduino.mk
+
+# --- leonardo (or pro micro w/leo bootloader)
+#BOARD_TAG    = leonardo
+#MONITOR_PORT = /dev/ttyACM0
+#include /usr/share/arduino/Arduino.mk
+
+# --- mega2560 ide 1.0
+#BOARD_TAG    = mega2560
+#ARDUINO_PORT = /dev/ttyACM0
+#include /usr/share/arduino/Arduino.mk
+
+# --- mega2560 ide 1.6
+#BOARD_TAG    = mega
+#BOARD_SUB    = atmega2560
+#MONITOR_PORT = /dev/ttyACM0
+#ARDUINO_DIR  = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- nano ide 1.0
+#BOARD_TAG    = nano328
+#MONITOR_PORT = /dev/ttyUSB0
+#include /usr/share/arduino/Arduino.mk
+
+# --- nano ide 1.6
+#BOARD_TAG   = nano
+#BOARD_SUB   = atmega328
+#ARDUINO_DIR = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- pro mini
+#BOARD_TAG    = pro5v328
+#MONITOR_PORT = /dev/ttyUSB0
+#include /usr/share/arduino/Arduino.mk
+
+# --- sparkfun pro micro
+#BOARD_TAG         = promicro16
+#ALTERNATE_CORE    = promicro
+#BOARDS_TXT        = $(HOME)/arduino/hardware/promicro/boards.txt
+#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/promicro/bootloaders
+#BOOTLOADER_PATH   = caterina
+#BOOTLOADER_FILE   = Caterina-promicro16.hex
+#ISP_PROG     	   = usbasp
+#AVRDUDE_OPTS 	   = -v
+#include /usr/share/arduino/Arduino.mk
+
+# --- chipkit
+#BOARD_TAG = mega_pic32
+#MPIDE_DIR = /where/you/installed/mpide-0023-linux64-20130817-test
+#include /usr/share/arduino/chipKIT.mk
+
+# --- pinoccio
+#BOARD_TAG         = pinoccio256
+#ALTERNATE_CORE    = pinoccio
+#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/pinoccio/bootloaders
+#BOOTLOADER_PATH   = STK500RFR2/release_0.51
+#BOOTLOADER_FILE   = boot_pinoccio.hex
+#CFLAGS_STD        = -std=gnu99
+#CXXFLAGS_STD      = -std=gnu++11
+#include /usr/share/arduino/Arduino.mk
+
+# --- fio
+#BOARD_TAG = fio
+#include /usr/share/arduino/Arduino.mk
+
+# --- atmega-ng ide 1.6
+#BOARD_TAG    = atmegang
+#BOARD_SUB    = atmega168
+#MONITOR_PORT = /dev/ttyACM0
+#ARDUINO_DIR  = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- arduino-tiny ide 1.0
+#ISP_PROG     	    = usbasp
+#BOARD_TAG          = attiny85at8
+#ALTERNATE_CORE     = tiny
+#ARDUINO_VAR_PATH   = $(HOME)/arduino/hardware/tiny/cores/tiny
+#ARDUINO_CORE_PATH  = $(HOME)/arduino/hardware/tiny/cores/tiny
+#AVRDUDE_OPTS 	    = -v
+#include /usr/share/arduino/Arduino.mk
+
+# --- arduino-tiny ide 1.6
+#ISP_PROG       = usbasp
+#BOARD_TAG      = attiny85at8
+#ALTERNATE_CORE = tiny
+#ARDUINO_DIR    = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- damellis attiny ide 1.0
+#ISP_PROG       = usbasp
+#BOARD_TAG      = attiny85
+#ALTERNATE_CORE = attiny-master
+#AVRDUDE_OPTS   = -v
+#include /usr/share/arduino/Arduino.mk
+
+# --- damellis attiny ide 1.6
+#ISP_PROG       = usbasp
+#BOARD_TAG      = attiny
+#BOARD_SUB      = attiny85
+#ALTERNATE_CORE = attiny
+#F_CPU          = 16000000L
+#ARDUINO_DIR    = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- teensy3
+#BOARD_TAG 	 = teensy31
+#ARDUINO_DIR = /where/you/installed/the/patched/teensy/arduino-1.0.6
+#include /usr/share/arduino/Teensy.mk
+
+# --- mighty 1284p
+#BOARD_TAG         = mighty_opt
+#BOARDS_TXT        = $(HOME)/arduino/hardware/mighty-1284p/boards.txt
+#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/mighty-1284p/bootloaders
+#BOOTLOADER_PATH   = optiboot
+#BOOTLOADER_FILE   = optiboot_atmega1284p.hex
+#ISP_PROG     	   = usbasp
+#AVRDUDE_OPTS 	   = -v
+#include /usr/share/arduino/Arduino.mk
+
+# --- atmega328p on breadboard
+#BOARD_TAG    = atmega328bb
+#ISP_PROG     = usbasp
+#AVRDUDE_OPTS = -v
+#BOARDS_TXT   = $(HOME)/arduino/hardware/breadboard/boards.txt
+#include /usr/share/arduino/Arduino.mk
diff --git a/examples/blink/README b/examples/blink/README
new file mode 100644
--- /dev/null
+++ b/examples/blink/README
@@ -0,0 +1,28 @@
+This is a demo program using arduino-copilot. 
+
+To build the C code:
+
+	runghc demo.hs
+
+The resulting `.ino` sketch can be loaded into the Arduino IDE and flashed
+to an Arduino board using the IDE.
+
+It simply flashes the Arduino's on board LED, so should work on most or all
+Arduino boards.
+
+## Arduino-Makefile integration
+
+The `Makefile` and `pre-build-hook.sh` show how to integrate arduino-copilot
+with <https://github.com/sudar/Arduino-Makefile>. This automates generating
+the C code, compiling that, and flashing it onto an Arduino Uno board,
+with a single command
+
+	make upload
+
+Note that you will need to manually build the C code once, as shown above
+, since the Arduino-Makefile expects to find a `.ino` file.
+
+The path in the `Makefile` to `Arduino.mk` may need to be adjusted (the
+default is the location where on a Debian system, `apt-get install
+arduino-mk` will install it). You may also adjust the `Makefile` to target
+a different board than the Arduino Uno.
diff --git a/examples/blink/demo.hs b/examples/blink/demo.hs
new file mode 100644
--- /dev/null
+++ b/examples/blink/demo.hs
@@ -0,0 +1,8 @@
+{-# LANGUAGE RebindableSyntax #-}
+
+import Copilot.Arduino
+
+main :: IO ()
+main = arduino $ do
+	led =: blinking
+	delay =: constant 100
diff --git a/examples/blink/pre-build-hook.sh b/examples/blink/pre-build-hook.sh
new file mode 100644
--- /dev/null
+++ b/examples/blink/pre-build-hook.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec runghc demo.hs
diff --git a/examples/button/Makefile b/examples/button/Makefile
new file mode 100644
--- /dev/null
+++ b/examples/button/Makefile
@@ -0,0 +1,127 @@
+# Arduino Make file. Refer to https://github.com/sudar/Arduino-Makefile
+BOARD_TAG    = uno
+include /usr/share/arduino/Arduino.mk
+
+# --- leonardo (or pro micro w/leo bootloader)
+#BOARD_TAG    = leonardo
+#MONITOR_PORT = /dev/ttyACM0
+#include /usr/share/arduino/Arduino.mk
+
+# --- mega2560 ide 1.0
+#BOARD_TAG    = mega2560
+#ARDUINO_PORT = /dev/ttyACM0
+#include /usr/share/arduino/Arduino.mk
+
+# --- mega2560 ide 1.6
+#BOARD_TAG    = mega
+#BOARD_SUB    = atmega2560
+#MONITOR_PORT = /dev/ttyACM0
+#ARDUINO_DIR  = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- nano ide 1.0
+#BOARD_TAG    = nano328
+#MONITOR_PORT = /dev/ttyUSB0
+#include /usr/share/arduino/Arduino.mk
+
+# --- nano ide 1.6
+#BOARD_TAG   = nano
+#BOARD_SUB   = atmega328
+#ARDUINO_DIR = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- pro mini
+#BOARD_TAG    = pro5v328
+#MONITOR_PORT = /dev/ttyUSB0
+#include /usr/share/arduino/Arduino.mk
+
+# --- sparkfun pro micro
+#BOARD_TAG         = promicro16
+#ALTERNATE_CORE    = promicro
+#BOARDS_TXT        = $(HOME)/arduino/hardware/promicro/boards.txt
+#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/promicro/bootloaders
+#BOOTLOADER_PATH   = caterina
+#BOOTLOADER_FILE   = Caterina-promicro16.hex
+#ISP_PROG     	   = usbasp
+#AVRDUDE_OPTS 	   = -v
+#include /usr/share/arduino/Arduino.mk
+
+# --- chipkit
+#BOARD_TAG = mega_pic32
+#MPIDE_DIR = /where/you/installed/mpide-0023-linux64-20130817-test
+#include /usr/share/arduino/chipKIT.mk
+
+# --- pinoccio
+#BOARD_TAG         = pinoccio256
+#ALTERNATE_CORE    = pinoccio
+#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/pinoccio/bootloaders
+#BOOTLOADER_PATH   = STK500RFR2/release_0.51
+#BOOTLOADER_FILE   = boot_pinoccio.hex
+#CFLAGS_STD        = -std=gnu99
+#CXXFLAGS_STD      = -std=gnu++11
+#include /usr/share/arduino/Arduino.mk
+
+# --- fio
+#BOARD_TAG = fio
+#include /usr/share/arduino/Arduino.mk
+
+# --- atmega-ng ide 1.6
+#BOARD_TAG    = atmegang
+#BOARD_SUB    = atmega168
+#MONITOR_PORT = /dev/ttyACM0
+#ARDUINO_DIR  = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- arduino-tiny ide 1.0
+#ISP_PROG     	    = usbasp
+#BOARD_TAG          = attiny85at8
+#ALTERNATE_CORE     = tiny
+#ARDUINO_VAR_PATH   = $(HOME)/arduino/hardware/tiny/cores/tiny
+#ARDUINO_CORE_PATH  = $(HOME)/arduino/hardware/tiny/cores/tiny
+#AVRDUDE_OPTS 	    = -v
+#include /usr/share/arduino/Arduino.mk
+
+# --- arduino-tiny ide 1.6
+#ISP_PROG       = usbasp
+#BOARD_TAG      = attiny85at8
+#ALTERNATE_CORE = tiny
+#ARDUINO_DIR    = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- damellis attiny ide 1.0
+#ISP_PROG       = usbasp
+#BOARD_TAG      = attiny85
+#ALTERNATE_CORE = attiny-master
+#AVRDUDE_OPTS   = -v
+#include /usr/share/arduino/Arduino.mk
+
+# --- damellis attiny ide 1.6
+#ISP_PROG       = usbasp
+#BOARD_TAG      = attiny
+#BOARD_SUB      = attiny85
+#ALTERNATE_CORE = attiny
+#F_CPU          = 16000000L
+#ARDUINO_DIR    = /where/you/installed/arduino-1.6.5
+#include /usr/share/arduino/Arduino.mk
+
+# --- teensy3
+#BOARD_TAG 	 = teensy31
+#ARDUINO_DIR = /where/you/installed/the/patched/teensy/arduino-1.0.6
+#include /usr/share/arduino/Teensy.mk
+
+# --- mighty 1284p
+#BOARD_TAG         = mighty_opt
+#BOARDS_TXT        = $(HOME)/arduino/hardware/mighty-1284p/boards.txt
+#BOOTLOADER_PARENT = $(HOME)/arduino/hardware/mighty-1284p/bootloaders
+#BOOTLOADER_PATH   = optiboot
+#BOOTLOADER_FILE   = optiboot_atmega1284p.hex
+#ISP_PROG     	   = usbasp
+#AVRDUDE_OPTS 	   = -v
+#include /usr/share/arduino/Arduino.mk
+
+# --- atmega328p on breadboard
+#BOARD_TAG    = atmega328bb
+#ISP_PROG     = usbasp
+#AVRDUDE_OPTS = -v
+#BOARDS_TXT   = $(HOME)/arduino/hardware/breadboard/boards.txt
+#include /usr/share/arduino/Arduino.mk
diff --git a/examples/button/README b/examples/button/README
new file mode 100644
--- /dev/null
+++ b/examples/button/README
@@ -0,0 +1,24 @@
+This is a demo program using arduino-copilot. 
+
+To build the C code:
+
+	runghc demo.hs
+
+The resulting `.ino` sketch can be loaded into the Arduino IDE and flashed
+to an Arduino Uno board using the IDE.
+
+## Arduino-Makefile integration
+
+The `Makefile` and `pre-build-hook.sh` show how to integrate arduino-copilot
+with <https://github.com/sudar/Arduino-Makefile>. This automates generating
+the C code, compiling that, and flashing it onto an Arduino Uno board,
+with a single command
+
+	make upload
+
+Note that you will need to manually build the C code once, as shown above
+, since the Arduino-Makefile expects to find a `.ino` file.
+
+The path in the `Makefile` to `Arduino.mk` may need to be adjusted (the
+default is the location where on a Debian system, `apt-get install
+arduino-mk` will install it).
diff --git a/examples/button/demo.hs b/examples/button/demo.hs
new file mode 100644
--- /dev/null
+++ b/examples/button/demo.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE RebindableSyntax #-}
+
+import Copilot.Arduino.Uno
+
+longer_and_longer :: Stream Int16
+longer_and_longer = counter true $ counter true false `mod` 64 == 0
+
+counter :: Stream Bool -> Stream Bool -> Stream Int16
+counter inc reset = cnt
+   where
+	cnt = if reset
+		then 0
+		else if inc
+			then z + 1
+			else z
+	z = [0] ++ cnt
+
+main :: IO ()
+main = arduino $ do
+	buttonpressed <- readfrom' pin12 [False, False, False, True, True]
+	led =: buttonpressed || blinking
+	delay =: longer_and_longer * 2
diff --git a/examples/button/pre-build-hook.sh b/examples/button/pre-build-hook.sh
new file mode 100644
--- /dev/null
+++ b/examples/button/pre-build-hook.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec runghc demo.hs
diff --git a/src/Arduino.hs b/src/Arduino.hs
deleted file mode 100644
--- a/src/Arduino.hs
+++ /dev/null
@@ -1,262 +0,0 @@
-{-# LANGUAGE RebindableSyntax #-}
-
-module Arduino (
-	module X,
-	-- * Arduino sketch generation
-	Sketch,
-	Input,
-	Output,
-	arduino,
-	-- * Combinators
-	(=:),
-	(@:),
-	-- * Inputs
-	boolInput,
-	boolInput',
-	-- TODO enumerate all avail pins, don't export constructor
-	Pin(..),
-	-- * Outputs
-	led,
-	MicroSeconds,
-	delay,
-	-- * Utilities
-	firstIteration,
-	sketchSpec,
-) where
-
-import Language.Copilot as X
-import Copilot.Compile.C99
-import System.Environment
-import System.Directory
-import System.Posix.Temp (mkdtemp)
-import System.FilePath
-import Text.Read
-import Control.Monad.Writer
-import Data.List (isInfixOf)
-import qualified Prelude
-
--- | An Arduino sketch, implemented using copilot.
---
--- On each iteration of a Sketch, all inputs used by it are first
--- collected, before any outputs are performed.
---
--- Like a copilot `Spec`, a Sketch's outputs are not run in any
--- particular order.
-type Sketch = Sketch' ()
-
-type Sketch' t = Writer [(Spec, Framework)] t
-
-data Framework = Framework
-	{ defines :: [CFragment]
-	, setups :: [CFragment]
-	, loops :: [CFragment]
-	}
-
-type CFragment = String
-
-instance Semigroup Framework where
-	a <> b = Framework
-		{ defines = defines a <> defines b
-		, setups = setups a <> setups b
-		, loops = loops a  <> loops b
-		}
-
-instance Monoid Framework where
-	mempty = Framework mempty mempty mempty
-
-class ToFramework t where
-	toFramework :: t -> Framework
-
-type Behavior t = Stream t -> Spec
-
--- | Somewhere that a Stream can be directed to, in order to control the
--- Arduino.
-data Output t = Output
-	{ setupOutput :: [CFragment]
-	, outputCond :: Stream Bool
-	, outputBehavior :: Stream Bool -> Behavior t
-	}
-
-instance ToFramework (Output t) where
-	toFramework o = Framework
-		{ defines = mempty
-		, setups = setupOutput o
-		, loops = mempty
-		}
-
--- | A source of a `Stream` of values input from the Arduino.
-type Input t = Sketch' (Stream t)
-
-data Input' t = Input'
-	{ defineVar :: [CFragment]
-	, setupInput :: [CFragment]
-	, readInput :: [CFragment]
-	, inputStream :: Stream t
-	}
-
-instance ToFramework (Input' t) where
-	toFramework i = Framework
-		{ defines = defineVar i
-		, setups = setupInput i
-		, loops = readInput i
-		}
-
--- | A GPIO pin
-newtype Pin = Pin Int
-
-mkInput :: Input' t -> Input t
-mkInput i = do
-	tell [(return (), toFramework i)]
-	return (inputStream i)
-
--- | Connect a `Stream` to an `Output`.
-(=:) :: Output t -> Stream t -> Sketch
-o =: s = tell [(go, toFramework o)]
-  where
-	go = (outputBehavior o) (outputCond o) s
-
--- Same fixity as =<<
-infixr 1 =:
-
--- | By default, an `Output` is written to on each iteration of the Sketch.
---
--- For example, this constantly turns on the LED, even though it will
--- already be on after the first iteration.
---
--- > led =: true
---
--- To avoid unnecessary work being done, this combinator can make an
--- `Output` only be written to when the current value of the provided
--- `Stream` is True.
---
--- So to make the LED only be turned on in the first iteration,
--- and allow it to remain on thereafter without doing extra work:
---
--- > led @: firstIteration =: true
-(@:) :: Output t -> Stream Bool -> Output t
-(@:) o c = o { outputCond = c }
-
--- | True on the first iteration of the Sketch, and False thereafter.
-firstIteration :: Stream Bool
-firstIteration = [True]++false
-
--- FIXME should be a newtype, but how to make a stream of a newtype?
-type MicroSeconds = Int16
-
--- | The on-board LED.
-led :: Output Bool
-led = Output
-	{ setupOutput = ["pinMode(13, OUTPUT)"]
-	, outputBehavior = 
-		\c v -> trigger "digitalWrite" c [arg (constI16 13), arg v]
-	, outputCond = true
-	}
-
--- | Use this to add a delay between each iteration of the Sketch.
-delay :: Output MicroSeconds
-delay = Output
-	{ setupOutput = []
-	, outputBehavior = \c n -> trigger "delay" c [arg n]
-	, outputCond = true
-	}
-
--- | Reading from a GPIO pin.
-boolInput :: Pin -> Input Bool
-boolInput n = boolInput' n []
-
--- | The optional list is used as simulated input
--- when interpreting the program.
-boolInput' :: Pin -> [Bool] -> Input Bool
-boolInput' (Pin n) interpretvalues = mkInput $ Input'
-	{ defineVar = ["bool " <> varname]
-	, setupInput = ["pinMode(" <> show n <> ", INPUT)"]
-	, readInput = [varname <> " = digitalRead(" <> show n <> ")"]
-	, inputStream = extern varname interpretvalues'
-	}
-  where
-	varname = "arduino_boolinput" <> show n
-	interpretvalues'
-		| null interpretvalues = Nothing
-		| otherwise = Just interpretvalues
-
--- | Typically your Arduino program's main will use this. For example:
---
--- > main = arduino $ do
--- >	led =: clk (period 2) (phase 1)
--- > 	delay =: const16 100
---
--- The `Sketch` is compiled into C code using copilot, and written
--- to a .ino file. That can be built and uploaded to your Arduino
--- using the Arduino IDE, or any other toolchain for Arduino sketches.
-arduino :: Sketch -> IO ()
-arduino s = do
-	let (is, fs) = unzip (execWriter s)
-	let spec = sequence_ is
-	-- TODO optparse-applicative
-	ps <- getArgs
-	case ps of
-		[] -> writeIno spec (mconcat fs)
-		["-i", n] -> case readMaybe n of
-			Just n' -> interpret n' spec
-			Nothing -> error "expected a number after -i"
-		_ -> error "bad parameters"
-
--- | Extracts a copilot `Spec` from a `Sketch`.
---
--- This can be useful to intergrate with other libraries 
--- such as copilot-theorem.
-sketchSpec :: Sketch -> Spec
-sketchSpec s = sequence_ is
-  where
-	(is, _fs) = unzip (execWriter s)
-
-writeIno :: Spec -> Framework -> IO ()
-writeIno spec framework = do
-	-- This could be a lot prettier, unfortunately copilot only exports
-	-- an interface that writes the generated code to a file.
-	-- And, the .c file includes a .h file that will make it fail to
-	-- build when used in the .ino file, so that include has to be
-	-- filtered out.
-	toptmpdir <- getTemporaryDirectory
-	mytmpdir <- mkdtemp (toptmpdir </> "copilot")
-	reify spec >>= compile (mytmpdir </> "copilot")
-	c <- lines <$> readFile (mytmpdir </> "copilot.c")
-	let c' = filter (Prelude.not . isInfixOf "#include \"") c
-	-- Use a name for the ino file that will let the Arduino IDE find it.
-	d <- getCurrentDirectory
-	let dirbase = takeFileName d
-	writeFile (addExtension dirbase "ino") $ 
-		sketchFramework framework c'
-	removeDirectoryRecursive mytmpdir
-	
-
-sketchFramework :: Framework -> [String] -> String
-sketchFramework f ccode = unlines $ concat
-	[
-		[ "/* automatically generated, do not edit */"
-		, blank
-		, "#include <stdbool.h>"
-		, "#include <stdint.h>"
-		, blank
-		]
-	, map statement (defines f)
-	, [blank]
-	, ccode
-	, [blank]
-	,
-		[ "void setup()"
-		]
-	, codeblock $ map statement (setups f)
-	, [blank]
-	,
-		[ "void loop()"
-		]
-	, codeblock $ map statement $ (loops f) <>
-		[ "step()"
-		]
-	]
-  where
-	blank = ""
-	indent l = "  " <> l
-	statement d = d <> ";"
-	codeblock l = ["{"] <> map indent l <> ["}"]
diff --git a/src/Copilot/Arduino.hs b/src/Copilot/Arduino.hs
new file mode 100644
--- /dev/null
+++ b/src/Copilot/Arduino.hs
@@ -0,0 +1,163 @@
+-- | Programming the Arduino with Copilot.
+--
+-- This module should work on any model of Arduino.
+-- See Arduino.Uno and Arduino.Nano for model-specific code.
+
+{-# LANGUAGE RebindableSyntax #-}
+
+module Copilot.Arduino (
+	-- * Arduino sketch generation
+	arduino,
+	Sketch,
+	Input,
+	Output,
+	Stream,
+	GPIO,
+	-- * Combinators
+	(=:),
+	(@:),
+	-- * Inputs
+	readfrom,
+	readfrom',
+	-- * Outputs
+	--
+	-- | Only outputs that work on all Arduino boards are included
+	-- here. Load a module such as Arduino.Uno for model-specific
+	-- outputs.
+	led,
+	writeto,
+	MicroSeconds,
+	delay,
+	-- * Utilities
+	blinking,
+	firstIteration,
+	sketchSpec,
+	-- * Copilot DSL
+	--
+	-- | The Copilot.Language module is re-exported here, including
+	-- a version of the Prelude modified for it. You should enable
+	-- the RebindableSyntax language extension in your program
+	-- to use the Copilot DSL.
+	--
+	-- > {-# LANGUAGE RebindableSyntax #-}
+	--
+	-- For documentation on using the Copilot DSL, see
+	-- <https://copilot-language.github.io/>
+	module Language.Copilot,
+) where
+
+import qualified Language.Copilot
+import Language.Copilot hiding (Stream)
+import Copilot.Arduino.Internals
+import Copilot.Arduino.Main
+import Control.Monad.Writer
+
+-- | A value that varies over time.
+--
+-- The Copilot DSL provides many operations on streams, for example
+-- `Language.Copilot.&&` to combine two streams of Bools.
+-- 
+-- For documentation on using the Copilot DSL, see
+-- <https://copilot-language.github.io/>
+type Stream t = Language.Copilot.Stream t
+
+-- | Connect a `Stream` to an `Output`.
+--
+-- > led := blinking
+(=:) :: Output t -> Stream t -> Sketch ()
+o =: s = tell [(go, toFramework o)]
+  where
+	go = (outputBehavior o) (outputCond o) s
+
+-- | Use this to make a LED blink on and off.
+--
+-- On each iteration of the `Sketch`, this changes to the opposite of its
+-- previous value.
+--
+-- This is implemented using Copilot's `clk`, so to get other blinking
+-- behaviors, just pick different numbers, or use Copilot `Stream`
+-- combinators.
+-- 
+-- > blinking = clk (period 2) (phase 1)
+blinking :: Stream Bool
+blinking = clk (period (2 :: Integer)) (phase (1 :: Integer))
+
+-- Same fixity as =<<
+infixr 1 =:
+
+-- | By default, an `Output` is written to on each iteration of the `Sketch`.
+--
+-- For example, this constantly turns on the LED, even though it will
+-- already be on after the first iteration.
+--
+-- > led =: true
+--
+-- To avoid unnecessary work being done, this combinator can make an
+-- `Output` only be written to when the current value of the provided
+-- `Stream` is True.
+--
+-- So to make the LED only be turned on in the first iteration,
+-- and allow it to remain on thereafter without doing extra work:
+--
+-- > led @: firstIteration =: true
+(@:) :: Output t -> Stream Bool -> Output t
+(@:) o c = o { outputCond = c }
+
+-- | True on the first iteration of the `Sketch`, and False thereafter.
+firstIteration :: Stream Bool
+firstIteration = [True]++false
+
+-- | Use this to add a delay between each iteration of the `Sketch`.
+-- A `Sketch` with no delay will run as fast as the hardware can run it.
+delay :: Output MicroSeconds
+delay = Output
+	{ setupOutput = []
+	, outputBehavior = \c n -> trigger "delay" c [arg n]
+	, outputCond = true
+	}
+
+-- | Reading from a GPIO pin.
+--
+-- > do
+-- > 	buttonpressed <- readfrom pin12
+-- > 	led := buttonpressed
+readfrom :: GPIO -> Input Bool
+readfrom n = readfrom' n []
+
+-- | The list is used as simulated input when interpreting the program.
+readfrom' :: GPIO -> [Bool] -> Input Bool
+readfrom' (GPIO n) interpretvalues = mkInput $ InputSource
+	{ defineVar = ["bool " <> varname]
+	, setupInput = ["pinMode(" <> show n <> ", INPUT)"]
+	, readInput = [varname <> " = digitalRead(" <> show n <> ")"]
+	, inputStream = extern varname interpretvalues'
+	}
+  where
+	varname = "arduino_gpio_input" <> show n
+	interpretvalues'
+		| null interpretvalues = Nothing
+		| otherwise = Just interpretvalues
+
+-- | Writing to a GPIO pin.
+writeto :: GPIO -> Output Bool
+writeto  (GPIO n) = Output
+	{ setupOutput = ["pinMode(" <> sn <> ", OUTPUT)"]
+	, outputBehavior = 
+		\c v -> trigger "digitalWrite" c [arg (constant n), arg v]
+	, outputCond = true
+	}
+  where
+	sn = show n
+
+-- | The on-board LED.
+led :: Output Bool
+led = writeto (GPIO 13)
+
+-- | Extracts a copilot `Spec` from a `Sketch`.
+--
+-- This can be useful to intergrate with other libraries 
+-- such as copilot-theorem.
+sketchSpec :: Sketch a -> Spec
+sketchSpec (Sketch s) = sequence_ is
+  where
+	(is, _fs) = unzip (execWriter s)
diff --git a/src/Copilot/Arduino/Internals.hs b/src/Copilot/Arduino/Internals.hs
new file mode 100644
--- /dev/null
+++ b/src/Copilot/Arduino/Internals.hs
@@ -0,0 +1,145 @@
+-- | You should not need to import this module unless you're adding support
+-- for a new model of Arduino, or an Arduino library.
+
+{-# LANGUAGE RebindableSyntax #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+module Copilot.Arduino.Internals where
+
+import Language.Copilot
+import Control.Monad.Writer
+
+-- | An Arduino sketch, implemented using Copilot.
+--
+-- It's best to think of the `Sketch` as a description of the state of the
+-- Arduino at any point in time.
+--
+-- Under the hood, the `Sketch` is run in a loop. On each iteration, it first
+-- reads all inputs and then updates outputs as needed. While it is a monad,
+-- a Sketch's outputs are not updated in any particular order, because
+-- Copilot does not guarantee any order.
+newtype Sketch t = Sketch (Writer [(Spec, Framework)] t)
+	deriving (Monad, Applicative, Functor, MonadWriter [(Spec, Framework)])
+
+instance Monoid (Sketch ()) where
+	mempty = Sketch (return ())
+
+instance Semigroup (Sketch t) where
+	(Sketch a) <> (Sketch b) = Sketch (a >> b)
+
+-- | The framework of an Arduino sketch.
+data Framework = Framework
+	{ defines :: [CFragment]
+	-- ^ Things that come before the C code generated by Copilot.
+	, setups :: [CFragment]
+	-- ^ Things to run in `setup`.
+	, loops :: [CFragment]
+	-- ^ Things to run in `loop`.
+	}
+
+-- | A fragment of C code.
+type CFragment = String
+
+instance Semigroup Framework where
+	a <> b = Framework
+		{ defines = defines a <> defines b
+		, setups = setups a <> setups b
+		, loops = loops a  <> loops b
+		}
+
+instance Monoid Framework where
+	mempty = Framework mempty mempty mempty
+
+class ToFramework t where
+	toFramework :: t -> Framework
+
+type Behavior t = Stream t -> Spec
+
+-- | Somewhere that a Stream can be directed to, in order to control the
+-- Arduino.
+data Output t = Output
+	{ setupOutput :: [CFragment]
+	-- ^ How to set up the output.
+	, outputCond :: Stream Bool
+	, outputBehavior :: Stream Bool -> Behavior t
+	}
+
+instance ToFramework (Output t) where
+	toFramework o = Framework
+		{ defines = mempty
+		, setups = setupOutput o
+		, loops = mempty
+		}
+
+-- | A source of a `Stream` of values input from the Arduino.
+--
+-- Runs in the `Sketch` monad.
+type Input t = Sketch (Stream t)
+
+data InputSource t = InputSource
+	{ defineVar :: [CFragment]
+	-- ^ Added to the `Framework`'s `defines`, this typically
+	-- defines a C variable.
+	, setupInput :: [CFragment]
+	-- ^ How to set up the input.
+	, readInput :: [CFragment]
+	-- ^ How to read a value from the input, this typically
+	-- reads a value into a C variable.
+	, inputStream :: Stream t
+	}
+
+instance ToFramework (InputSource t) where
+	toFramework i = Framework
+		{ defines = defineVar i
+		, setups = setupInput i
+		, loops = readInput i
+		}
+
+mkInput :: InputSource t -> Input t
+mkInput i = do
+	tell [(return (), toFramework i)]
+	return (inputStream i)
+
+-- | A GPIO pin
+--
+-- For definitions of GPIO pins like `Copilot.Arduino.Uno.pin12`, 
+-- load a module such as Copilot.Arduino.Uno, which provides the pins of a
+-- particular board.
+newtype GPIO = GPIO Int16
+
+-- FIXME should be a newtype, but how to make a stream of a newtype?
+type MicroSeconds = Int16
+
+-- | Makes an arduino sketch, using a Framework, and a list of lines of C
+-- code generated by Copilot.
+sketchFramework :: Framework -> [String] -> [CFragment]
+sketchFramework f ccode = concat
+	[
+		[ "/* automatically generated, do not edit */"
+		, blank
+		, "#include <stdbool.h>"
+		, "#include <stdint.h>"
+		, blank
+		]
+	, map statement (defines f)
+	, [blank]
+	, ccode
+	, [blank]
+	,
+		[ "void setup()"
+		]
+	, codeblock $ map statement (setups f)
+	, [blank]
+	,
+		[ "void loop()"
+		]
+	, codeblock $ map statement $ (loops f) <>
+		[ "step()"
+		]
+	]
+  where
+	blank = ""
+	indent l = "  " <> l
+	statement d = d <> ";"
+	codeblock l = ["{"] <> map indent l <> ["}"]
diff --git a/src/Copilot/Arduino/Main.hs b/src/Copilot/Arduino/Main.hs
new file mode 100644
--- /dev/null
+++ b/src/Copilot/Arduino/Main.hs
@@ -0,0 +1,84 @@
+module Copilot.Arduino.Main (arduino) where
+
+import Language.Copilot (Spec, interpret, reify)
+import Copilot.Compile.C99 (compile)
+import Copilot.Arduino.Internals
+import System.Directory
+import System.Posix.Temp (mkdtemp)
+import System.FilePath
+import Control.Monad.Writer
+import Data.List (isInfixOf)
+import Options.Applicative
+
+-- | Typically your Arduino program's main will be implemented using this.
+-- For example:
+--
+-- > {-# LANGUAGE RebindableSyntax #-}
+-- > 
+-- > import Copilot.Arduino
+-- > 
+-- > main = arduino $ do
+-- >	led =: flashing
+-- > 	delay =: constant 100
+--
+-- Running this program compiles the `Sketch` into C code using copilot, and
+-- writes it to a .ino file. That can be built and uploaded to your Arduino
+-- using the Arduino IDE, or any other toolchain for Arduino sketches.
+--
+-- This also supports interpreting a `Sketch`, without loading it onto an
+-- Arduino. Run the program with parameters "-i 4" to display what it
+-- would do on the first 4 iterations. The output will look something like
+-- this:
+--
+-- > delay:         digitalWrite: 
+-- > (100)          (13,false)    
+-- > (100)          (13,true)     
+-- > (100)          (13,false)    
+-- > (100)          (13,true)     
+arduino :: Sketch () -> IO ()
+arduino (Sketch s) = go =<< execParser opts
+  where
+	opts = info (parseCmdLine <**> helper)
+		( fullDesc
+		<> progDesc "Run this program with no options to generate an Arduino sketch."
+		)
+
+	go o = case interpretSteps o of
+		Just n -> interpret n spec
+		Nothing -> writeIno spec (mconcat fs)
+	
+	(is, fs) = unzip (execWriter s)
+	spec = sequence_ is
+
+data CmdLine = CmdLine
+	{ interpretSteps :: Maybe Integer
+	}
+
+
+parseCmdLine :: Parser CmdLine
+parseCmdLine = CmdLine
+	<$> optional (option auto
+		( long "interpret"
+		<> short 'i'
+		<> help "use copilot to interpret the program, displaying what it would do"
+		<> metavar "NUM"
+		))
+
+writeIno :: Spec -> Framework -> IO ()
+writeIno spec framework = do
+	-- This could be a lot prettier, unfortunately copilot only exports
+	-- an interface that writes the generated code to a file.
+	-- And, the .c file includes a .h file that will make it fail to
+	-- build when used in the .ino file, so that include has to be
+	-- filtered out.
+	toptmpdir <- getTemporaryDirectory
+	mytmpdir <- mkdtemp (toptmpdir </> "copilot")
+	reify spec >>= compile (mytmpdir </> "copilot")
+	c <- lines <$> readFile (mytmpdir </> "copilot.c")
+	let c' = filter (Prelude.not . isInfixOf "#include \"") c
+	-- Use a name for the ino file that will let the Arduino IDE find it.
+	d <- getCurrentDirectory
+	let dirbase = takeFileName d
+	writeFile (addExtension dirbase "ino") $ 
+		unlines $ sketchFramework framework c'
+	removeDirectoryRecursive mytmpdir
diff --git a/src/Copilot/Arduino/Nano.hs b/src/Copilot/Arduino/Nano.hs
new file mode 100644
--- /dev/null
+++ b/src/Copilot/Arduino/Nano.hs
@@ -0,0 +1,51 @@
+-- | Programming the Arduino Nano with Copilot.
+
+module Copilot.Arduino.Nano (
+	-- * General Arduino programming infrastructure
+	module Copilot.Arduino
+	-- * GPIO
+	, pin2
+	, pin3
+	, pin4
+	, pin5
+	, pin6
+	, pin7
+	, pin8
+	, pin9
+	, pin10
+	, pin11
+	, pin12
+	, pin13
+	-- * Analog input
+	-- TODO!
+	--, a0
+	--, a1
+	--, a2
+	--, a3
+	--, a4
+	--, a5
+	--, a6
+	--, a7
+	-- * UART
+	-- Not currently supported!
+	--, uart
+) where
+
+import Copilot.Arduino
+import Copilot.Arduino.Internals
+
+pin2, pin3, pin4, pin5, pin6, pin7, pin8, pin9, pin10, pin11, pin12, pin13 :: GPIO
+pin2 = GPIO 2
+pin3 = GPIO 3
+pin4 = GPIO 4
+pin5 = GPIO 5
+pin6 = GPIO 6
+pin7 = GPIO 7
+pin8 = GPIO 8
+pin9 = GPIO 9
+pin10 = GPIO 10
+pin11 = GPIO 11
+pin12 = GPIO 12
+-- | This pin is connected to the `led`
+pin13 = GPIO 13
+
diff --git a/src/Copilot/Arduino/Uno.hs b/src/Copilot/Arduino/Uno.hs
new file mode 100644
--- /dev/null
+++ b/src/Copilot/Arduino/Uno.hs
@@ -0,0 +1,49 @@
+-- | Programming the Arduino Uno with Copilot.
+
+module Copilot.Arduino.Uno (
+	-- * General Arduino programming infrastructure
+	module Copilot.Arduino
+	-- * GPIO
+	, pin2
+	, pin3
+	, pin4
+	, pin5
+	, pin6
+	, pin7
+	, pin8
+	, pin9
+	, pin10
+	, pin11
+	, pin12
+	, pin13
+	-- * Analog input
+	-- TODO!
+	--, a0
+	--, a1
+	--, a2
+	--, a3
+	--, a4
+	--, a5
+	-- * UART
+	-- Not currently supported!
+	--, uart
+) where
+
+import Copilot.Arduino
+import Copilot.Arduino.Internals
+
+pin2, pin3, pin4, pin5, pin6, pin7, pin8, pin9, pin10, pin11, pin12, pin13 :: GPIO
+pin2 = GPIO 2
+pin3 = GPIO 3
+pin4 = GPIO 4
+pin5 = GPIO 5
+pin6 = GPIO 6
+pin7 = GPIO 7
+pin8 = GPIO 8
+pin9 = GPIO 9
+pin10 = GPIO 10
+pin11 = GPIO 11
+pin12 = GPIO 12
+-- | This pin drives the `led`
+pin13 = GPIO 13
+
